2011-08-24 7 views
16

Antecedentes:¿Cómo se formatea una tarjeta SD utilizando la API de almacenamiento a través de Windows Mobile 6

Estoy intentando crear una utilidad que permitirá a nuestros clientes para dar formato fácilmente una tarjeta SD (en realidad mini-SD) directamente en un dispositivo con Windows Mobile 6 (Intermec CK3). Esto sería preferible a una herramienta de terceros como FlashFormat o tener que proporcionar lectores de tarjetas a los clientes (lo que requeriría que extraigan la batería, extraigan la tarjeta mini-SD que está sujeta por una carcasa de metal endeble, y luego ejecutar la utilidad de formateo de Windows a través del control de gestión de archivos). La mayoría de nuestros clientes no son muy conocedores de la tecnología, por lo que una utilidad que se puede ejecutar automáticamente o con un par de clics sería ideal.

He intentado lo siguiente hasta el momento:

  • Mirado this cuestión. Las respuestas aquí no parecen funcionar para Windows Mobile (por ejemplo, no hay soporte WMI o utilidad format.com).
  • Probado utilizando CreateFile y DeviceIoControlCE. Este parecía prometedor, pero la tarjeta SD nunca parece formatear realmente. Por lo que pude ver, fue porque primero era necesario desmontar la tarjeta.
  • Probado usando CreatFile y FormatVolumeEx (junto con las otras variantes, FormatVolume y FormateVolumeUI). El resultado parecía ser similar en el sentido de que no podía formatear la tarjeta a menos que primero se desmontara.

Después de hacer algunas búsquedas en un funcionamiento en this thread (respuesta cerca del fondo por paraGOD) y this blog, decidí ir por un nuevo camino de utilizar el Store Manager API, que tiene las funciones que FindFirstStore, FindNextStore, OpenStore, DismountStore y pronto.

Estoy intentando hacer esto en C#, así que creé las estructuras de soporte necesarias para representar los typdefs utilizados en la API. Aquí está una muestra de 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; 
    } 
} 

Luego he creado una clase estática gestor de almacenamiento para contener todas las funciones de administrador de almacenamiento (que se supone que deben estar disponibles en coredll para Windows Mobile 6 ... o eso creía yo) :

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 

así que fui a probar algunas de estas funciones, tales como una simple enumeración través de las tiendas a través de las funciones y FindFirstStore FindNextStore y entonces consigo la temida, no puede encontrar 'FindFirstStore' punto de entrada en una DLL de PInvoke 'Coredll.dll' error (en e salida del depurador También recibo Se produjo una primera excepción de tipo 'System.MissingMethodException' en SDFormatter.exe, lo cual tiene sentido). Algunas investigaciones más insinuaron que en Windows Mobile, estas funciones no están expuestas, a pesar de que son parte de Coredll. Sin embargo, son parte de Windows CE 6 y se puede acceder a través del creador de plataforma.

Así que aquí son las principales preguntas que tengo:

  • ¿Puedo acceder a la API de almacenamiento a través de C# en Windows Mobile 6 de alguna forma?
  • Si no es así, ¿puedo escribir una utilidad a través de C++ administrado (no sé mucho, pero voy a tropezar si es necesario), pero sin tener que usar el creador de plataformas (no es gratis)?
  • Si solo es posible a través del creador de plataformas, ¿eso significa que estoy atascado construyendo mi propio SDK o tendré que pedirle a Intermec que me exponga la funcionalidad?

También estoy dispuesto a hacer esto de otra manera (preferiblemente a través de C#) si alguien tiene alguna sugerencia. Estaba pensando que tal vez el cliente podría montar el dispositivo en la cuna y ejecutar una utilidad de escritorio. No estoy seguro de si esto es posible y no puede confiar en ActiveSync (no queremos admitir otra herramienta más, por lo que enviamos datos hacia y desde la tarjeta SD a través de un adaptador de red conectado a la base usando conectores para hablar entre programa de servidor personalizado y nuestra aplicación móvil).

Gracias

+0

me encontré con este hilo de 2009 del grupo de noticias que podrían ser relevantes: http://www.pocketpcjunkies.com/Uwe/Forum.aspx/wince-pb/21443/StoreApi-Lib-not-exported-in-the-SDK-and-linking-di-rect-doesn – PaulH

Respuesta

0

FindFirstStore está disponible en Windows Mobile 5.0 y dispositivos posteriores de la API pública, por lo que no es necesario ningún procedimiento especial como constructor de la plataforma.

Creo que leí en alguna parte que FindFirstStore solo se movió a coredll.dll en CE6 (no recuerdo dónde vi eso). Por lo tanto, es probable que su dispositivo Windows Mobile 6 lo haya exportado desde otro lugar. (Posiblemente storeapi.dll?)

intente crear un proyecto de C++ con el código y ver si funciona para usted:

#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

Voy a probarlo mañana (puede que tenga que esperar hasta el miércoles) y le contaré cómo va. Gracias por la sugerencia. –

+0

Intenté construir algo como esto en el código nativo hace unos días cuando vi esta pregunta y no se puede vincular porque los SDK de WinMo (5.0 y 6.0) no incluyen 'storeapi.lib'. También verifiqué todos y no encontré nada. – ctacke

+0

@ctacke - Acabo de volver a mi PC para probar esto yo mismo. Estás en lo correcto. storeapi.lib es parte de las fuentes de Windows Mobile incluidas con el creador de plataformas. 'PUBLIC \ COMMON \ OAK \ LIB \ ARMV4I \ RETAIL \ storeapi.lib'. Si conoce una forma de extraer el ordinal de la biblioteca de importación, los buscaré y podrá importar las funciones por ordinal. – PaulH

2

teníamos el mismo requisito exacto, pero en Windows CE. Nuestra solución fue crear una pequeña aplicación C++, que luego se llama desde el código C#. Esta es la parte más importante de la aplicación 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); 
} 
Cuestiones relacionadas