2011-08-24 5 views
16

Background:Come si formatta una scheda SD utilizzando l'API Storage Manager tramite Windows Mobile 6

Sto cercando di creare un programma di utilità che permetterà ai nostri clienti di formato facilmente una scheda SD (in realtà mini-SD) direttamente su un dispositivo Windows Mobile 6 (Intermec CK3). Ciò sarebbe preferibile a uno strumento di terze parti come FlashFormat o a fornire lettori di schede ai clienti (che richiederebbero loro di rimuovere la batteria, estrarre la scheda mini-SD che è contenuta da un involucro di metallo sottile, quindi eseguire l'utilità di formattazione di Windows tramite il controllo di gestione dei file). La maggior parte dei nostri clienti non sono molto esperti di tecnologia, quindi un'utilità che può essere eseguita automaticamente o con un paio di clic sarebbe l'ideale.

Ho provato la seguente finora:

  • Guardato this domanda. Le risposte qui non sembrano funzionare per Windows Mobile (ad esempio nessun supporto WMI o utility format.com).
  • Provato usando CreateFile e DeviceIoControlCE. Questo sembrava promettente, ma la scheda SD non sembrerebbe mai realmente formattata. Da quello che ho potuto dire, è stato perché la carta doveva essere smontata prima.
  • Provato con CreatFile e FormatVolumeEx (insieme con le altre varianti, FormatVolume e FormateVolumeUI). Il risultato sembrava essere simile in quanto non potevo formattare la scheda a meno che non fosse prima smontata.

Dopo aver fatto qualche ricerca di una esecuzione in this thread (risposta nei pressi di fondo da paraGOD) e this blog, ho deciso di andare giù un nuovo percorso di usare la Store Manager API, che ha funzioni come FindFirstStore, FindNextStore, OpenStore, DismountStore e presto.

Sto provando a farlo in C#, quindi ho creato le strutture di supporto necessarie per rappresentare i typdefs utilizzati nell'API. Ecco un esempio uno:

using System.Runtime.InteropServices; 

// Try to match the struct typedef exactly (all caps, exact type names). 
using DWORD = System.UInt32; 
using TCHAR = System.String; 

namespace SDFormatter 
{ 
    // http://msdn.microsoft.com/en-us/library/ee490035(v=WinEmbedded.60).aspx 
    // STORAGEDEVICEINFO (Storage Manager) 

    [StructLayout(LayoutKind.Sequential)] 
    public struct StorageDeviceInfo 
    { 
     public DWORD cbSize; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] 
     public TCHAR szProfile; 
     public DWORD dwDeviceClass; 
     public DWORD dwDeviceType; 
     public DWORD dwDeviceFlags; 
    } 
} 

Poi ho creato una classe di storage manager statica per contenere tutte le funzioni storage manager (che dovrebbero essere disponibili nel coredll per Windows Mobile 6 ... o almeno così pensavo) :

using System.Runtime.InteropServices; 

// Try to match the Coredll functions exactly (all caps, exact type names, etc.). 
using BOOL = System.Boolean; 
using BYTE = System.Byte; 
using DWORD = System.UInt32; 
using HANDLE = System.IntPtr; 
using LPCE_VOLUME_INFO = System.IntPtr; 
using LPCSTR = System.String; 
using LPCTSTR = System.String; 
using LPCWSTR = System.String; 
using PPARTINFO = System.IntPtr; 
using PSTOREINFO = System.IntPtr; 
using SECTORNUM = System.UInt64; 

// ReSharper disable InconsistentNaming 
namespace SDFormatter 
{ 
    // http://msdn.microsoft.com/en-us/library/ee490420(v=WinEmbedded.60).aspx 

    public static class StorageManager 
    { 
     [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     public static extern bool CeGetVolumeInfo(LPCWSTR pszRootPath, CE_VOLUME_INFO_LEVEL InfoLevel, 
                LPCE_VOLUME_INFO lpVolumeInfo); 

     [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     public static extern bool CreatePartition(HANDLE hStore, LPCTSTR szPartitionName, SECTORNUM snNumSectors); 

     [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     public static extern bool CreatePartitionEx(HANDLE hStore, LPCTSTR szPartitionName, BYTE bPartType, 
                SECTORNUM snNumSectors); 

     [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     public static extern bool DeletePartition(HANDLE hStore, LPCTSTR szPartitionName); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool DismountPartition(HANDLE hPartition); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool DismountStore(HANDLE hStore); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool FindClosePartition(HANDLE hSearch); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool FindCloseStore(HANDLE hSearch); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern HANDLE FindFirstPartition(HANDLE hStore, PPARTINFO pPartInfo); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern HANDLE FindFirstStore(PSTOREINFO pStoreInfo); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool FindNextPartition(HANDLE hSearch, PPARTINFO pPartInfo); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool FindNextStore(HANDLE hSearch, PSTOREINFO pStoreInfo); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool FormatPartition(HANDLE hPartition); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool FormatPartitionEx(HANDLE hPartition, BYTE bPartType, BOOL bAuto); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool FormatStore(HANDLE hStore); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool GetPartitionInfo(HANDLE hPartition, PPARTINFO pPartInfo); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool GetStoreInfo(HANDLE hStore, PSTOREINFO pStoreInfo); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool MountPartition(HANDLE hPartition); 

     [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     public static extern HANDLE OpenPartition(HANDLE hStore, LPCTSTR szPartitionName); 

     [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     public static extern HANDLE OpenStore(LPCSTR szDeviceName); 

     [DllImport("Coredll.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
     public static extern bool RenamePartition(HANDLE hPartition, LPCTSTR szNewName); 

     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool SetPartitionAttributes(HANDLE hPartition, DWORD dwAttrs); 

     // http://msdn.microsoft.com/en-us/library/ee490442(v=winembedded.60).aspx 
     [DllImport("Coredll.dll", SetLastError = true)] 
     public static extern bool CloseHandle(HANDLE hObject); 
    } 

    public enum CE_VOLUME_INFO_LEVEL 
    { 
     CeVolumeInfoLevelStandard = 0 
    } 
} 
// ReSharper restore InconsistentNaming 

Così sono andato a provare alcune di queste funzioni, come ad esempio semplicemente enumerazione attraverso i negozi tramite le funzioni FindFirstStore e FindNextStore e poi ho temuto, Impossibile trovare 'FindFirstStore' un punto di ingresso in un errore "Coredll.dll" PInvoke DLL (in th output di debugger ottengo anche Una prima eccezione di tipo "System.MissingMethodException" si è verificata in SDFormatter.exe, il che ha senso). Altre ricerche hanno fatto capire che in Windows Mobile queste funzioni non sono esposte, anche se fanno parte di Coredll. Sono tuttavia parte di Windows CE 6 e sono accessibili tramite il programma di sviluppo della piattaforma.

Così qui sono le principali domande che ho:

  • Posso accedere all'API Storage Manager tramite C# in Windows Mobile 6 in qualche modo?
  • In caso contrario, posso scrivere un programma di utilità tramite C++ gestito (non so molto, ma lo troverò se necessario), ma senza dover utilizzare il costruttore di piattaforme (non è gratuito)?
  • Se è possibile solo tramite il generatore di piattaforme, vuol dire che sono bloccato a costruire il mio SDK o dovrò chiedere a Intermec di esporre la funzionalità per me?

Sono anche aperto a farlo in un altro modo completamente (preferibilmente tramite C#) se qualcuno ha suggerimenti. Stavo pensando che forse il cliente avrebbe potuto montare il dispositivo nella base e gestire un'utility desktop. Non sono sicuro se ciò è possibile e non può fare affidamento su ActiveSync (non vogliamo supportare ancora un altro strumento, quindi inviamo i dati da e verso la scheda SD tramite un adattatore di rete collegato alla base tramite prese per parlare tra i nostri programma server personalizzato e la nostra applicazione mobile).

Grazie

+0

mi sono imbattuto in questo 2009 discussione newsgroup che potrebbero essere rilevanti: http://www.pocketpcjunkies.com/Uwe/Forum.aspx/wince-pb/21443/StoreApi-Lib-not-exported-in-the-SDK-and-linking-di-rect-doesn – PaulH

risposta

0

FindFirstStore è disponibile su Windows Mobile 5.0 e dispositivi successivi nella API pubblica, quindi non dovrebbe essere necessario qualcosa di fantasia come Platform Builder.

Penso di aver letto da qualche parte che FindFirstStore è stato spostato solo in coredll.dll in CE6 (non riesco a ricordare dove l'ho visto). Quindi, il tuo dispositivo Windows Mobile 6 probabilmente lo esporterà da qualche altra parte. (Possibilmente storeapi.dll?)

provare a creare un progetto di C++ con questo codice e vedere se funziona per voi:

#pragma comment(lib, "storeapi.lib") 

int _tmain(int /*argc*/, _TCHAR* /*argv*/[]) 
{ 
    STOREINFO si = { 0 }; 
    si.cbSize = sizeof(STOREINFO); 

    HANDLE ffs = ::FindFirstStore(&si); 
    if(INVALID_HANDLE_VALUE != ffs) 
    { 
     ::FindCloseStore(ffs); 
    } 
    return 0; 
} 
+0

Ci andrò domani (potrebbe dover aspettare fino a mercoledì) e farti sapere come va. Grazie per il suggerimento. –

+0

Ho provato a creare qualcosa di simile nel codice nativo pochi giorni fa quando ho visto questa domanda e non riesce a collegarsi perché gli SDK di WinMo (5.0 e 6.0) non includono 'storeapi.lib'. Ho anche controllato Coredll e non ho trovato nulla. – ctacke

+0

@ctacke - Sono appena tornato al mio PC per provare da solo. Hai ragione storeapi.lib fa parte delle fonti di Windows Mobile incluse con il builder della piattaforma. 'Public \ Common \ Oak \ lib \ ARMV4I \ Retail \ storeapi.lib'. Se si è a conoscenza di un modo per ottenere l'ordinale dalla libreria di importazione, cercherò quelli in alto e lui può importare le funzioni per ordinale. – PaulH

2

abbiamo avuto la stessa identica requisito, ma su Windows CE. La nostra soluzione era creare una piccola applicazione C++, che viene poi chiamata dal codice C#. Qui è la parte più importante di applicazione C++:

#include <windows.h> 
#include <Storemgr.h> 

int _tmain(int /*argc*/, _TCHAR* /*argv*/[]) 
{ 
    WCHAR szDisk[] = L"DSK0"; 

    hDsk = OpenStore(szDisk); 
    if(hDsk == INVALID_HANDLE_VALUE) 
     // ERROR : Opening Store 

    if (!GetStoreInfo(hDsk, &si)) 
     // ERROR : Getting Store Info 

    if(!DismountStore(hDsk)) 
     // ERROR : Dismounting Store 

    if(!FormatStore(hDsk)) 
     // ERROR : Formatting Store 

    CloseHandle(hDsk); 
} 
Problemi correlati