c# - portable - ¿Cómo formatear una tarjeta SD utilizando la API del Administrador de almacenamiento a través de Windows Mobile 6?
net framework 3.5 portable download (2)
Teníamos exactamente el mismo requisito, pero en Windows CE. Nuestra solución fue crear una pequeña aplicación de C ++, que luego se llama desde el código C #. Aquí está 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);
}
Fondo:
Estoy intentando crear una utilidad que permita a nuestros clientes formatear fácilmente una tarjeta SD (en realidad, mini-SD) directamente en un dispositivo con Windows Mobile 6 (Intermec CK3). Esto se preferiría a una herramienta de terceros, como FlashFormat o el hecho de tener que proporcionar lectores de tarjetas a los clientes (lo que requeriría que extrajeran la batería, extraer la tarjeta mini-SD que está sujeta por una carcasa metálica endeble, y luego ejecute 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 expertos en tecnología, por lo que una utilidad que puede ejecutarse automáticamente o mediante un par de clics sería ideal.
He intentado lo siguiente hasta ahora:
- Miré this pregunta. Las respuestas aquí no parecen funcionar para Windows Mobile (por ejemplo, no es compatible con WMI o la utilidad format.com).
- Intentado usando CreateFile y DeviceIoControlCE . Esta parecía prometedora, pero la tarjeta SD nunca se formatearía realmente. Por lo que pude ver, fue porque la tarjeta tenía que ser desmontada primero.
- CreateFile usar CreateFile y FormatVolumeEx (junto con las otras variantes, FormatVolume y FormateVolumeUI ). El resultado parecía ser similar, ya que no podía formatear la tarjeta a menos que se desmontara por primera vez.
Después de hacer una búsqueda y ejecución en este hilo (respuesta casi al final por paraGOD) y este blog , decidí seguir una nueva ruta de uso de la API del Administrador de la Tienda , que tiene funciones tales como FindFirstStore , OpenStore , OpenStore , DismountStore , etc. .
Estoy tratando de hacer esto en C #, así que creé las estructuras de soporte necesarias para representar los typdefs utilizados en la API. Aquí hay una muestra:
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 creé una clase de administrador de almacenamiento estático para mantener todas las funciones del administrador de almacenamiento (que se supone están 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, como simplemente enumerar a través de las tiendas a través de las funciones FindFirstStore y FindNextStore y luego obtengo el temido, No puedo encontrar un punto de entrada ''FindFirstStore'' en un error PInvoke DLL ''Coredll.dll'' (en la salida del depurador también obtengo una excepción de primera oportunidad del tipo ''System.MissingMethodException'' ocurrió en SDFormatter.exe , lo cual tiene sentido). Un poco más de investigación sugirió 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 la plataforma.
Así que aquí están las principales preguntas que tengo:
- ¿Puedo acceder a la API de Storage Manager a través de C # en Windows Mobile 6 de alguna manera?
- Si no es así, ¿puedo escribir una utilidad a través de C ++ administrado (no sé mucho, pero me tropezaré si es necesario), pero sin tener que usar Platform Builder (no es gratis)?
- Si solo es posible a través de Platform Builder, ¿significa que estoy bloqueando mi propio SDK o tendré que pedirle a Intermec que me muestre la funcionalidad?
También estoy abierto a hacer esto de otra manera completamente (preferiblemente a través de C #) si alguien tiene sugerencias. Estaba pensando que tal vez el cliente debería montar el dispositivo en la base y ejecutar una utilidad de escritorio. No estoy seguro de si esto es posible y no puede confiar en ActiveSync (no queremos admitir ninguna otra herramienta, por lo que enviamos datos hacia y desde la tarjeta SD a través de un adaptador de red conectado a la base mediante sockets para hablar entre nuestros programa de servidor personalizado y nuestra aplicación móvil).
Gracias
FindFirstStore está disponible en Windows Mobile 5.0 y dispositivos posteriores en la API pública, por lo que no debería necesitar nada sofisticado como el creador de plataformas.
Creo que leí en alguna parte que FindFirstStore solo se movió a coredll.dll en CE6 (no recuerdo dónde lo vi). Por lo tanto, su dispositivo Windows Mobile 6 probablemente lo tendrá exportado desde otro lugar. (posiblemente storeapi.dll?)
Intente crear un proyecto en C ++ con este código y vea 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;
}