Задний план:
Я пытаюсь создать утилиту, которая позволит нашим клиентам легко форматировать SD-карту (на самом деле mini-SD) прямо на устройстве Windows Mobile 6 (Intermec CK3). Это предпочтительнее стороннего инструмента, такого как FlashFormat. или необходимость предоставлять клиентам устройства чтения карт (что потребовало бы от них снятия батареи, вытаскивания мини-SD-карты, удерживаемой хлипким металлическим корпусом, а затем запуска утилиты форматирования Windows через элемент управления файлами). Большинство наших клиентов не очень разбираются в технологиях, поэтому утилита, которая может запускаться автоматически или с помощью пары щелчков мыши, была бы идеальной.
До сих пор я пробовал следующее:
- Посмотрел этот вопрос. Ответы здесь, похоже, не работают для Windows Mobile (например, нет поддержки WMI или утилиты format.com).
- Пробовал использовать CreateFile и DeviceIoControlCE. Это казалось многообещающим, но SD-карта никогда не форматировалась. Насколько я могу судить, это произошло потому, что карту нужно было сначала снять.
- Пробовал использовать CreatFile и FormatVolumeEx (наряду с другими вариантами, FormatVolume и FormateVolumeUI). Результат был похож, так как я не мог отформатировать карту, пока она не была сначала отключена.
После некоторого поиска обнаружил этот тред (ответ paraGOD внизу) и этот блог, я решил перейти по новому пути использования Store Manager API, который имеет такие функции, как FindFirstStore, FindNextStore, OpenStore, DismountStore и так далее.
Я пытаюсь сделать это на C #, поэтому я создал необходимые вспомогательные структуры для представления определений типов, используемых в API. Вот пример:
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;
}
}
Затем я создал класс статического диспетчера хранилища для хранения всех функций диспетчера хранилища (которые должны быть доступны в coredll для Windows Mobile 6 ... или мне так казалось):
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
Итак, я пошел протестировать некоторые из этих функций, например, просто перечислить магазины с помощью функций FindFirstStore и FindNextStore, а затем получил ужасное сообщение: Не могу найти точку входа FindFirstStore в библиотеке PInvoke. Ошибка «Coredll.dll» (в выходных данных отладчика я также получаю Первое случайное исключение типа «System.MissingMethodException», возникшее в SDFormatter.exe strong>, что имеет смысл). Еще одно исследование показало, что в Windows Mobile эти функции не доступны, хотя они являются частью Coredll. Однако они являются частью Windows CE 6 и могут быть доступны через конструктор платформы.
Итак, вот основные вопросы, которые у меня есть:
- Могу ли я каким-то образом получить доступ к Storage Manager API через C # в Windows Mobile 6?
- Если нет, могу ли я написать утилиту через управляемый C ++ (я мало что знаю, но при необходимости наткнусь на нее), но без использования конструктора платформ (это не бесплатно)?
- Если это возможно только через конструктор платформ, означает ли это, что я либо застрял в создании собственного SDK, либо мне придется попросить Intermec предоставить мне эту функциональность?
Я также открыт для того, чтобы сделать это совершенно другим способом (предпочтительно через C #), если у кого-то есть предложения. Я подумал, может быть, заказчик установит устройство в подставку и запустит настольную утилиту. Не уверен, возможно ли это, и он не может полагаться на ActiveSync (мы не хотим поддерживать еще один инструмент, поэтому мы отправляем данные на SD-карту и с нее через сетевой адаптер, подключенный к подставке, используя разъемы для разговора между нашими кастомная серверная программа и наше мобильное приложение).
Спасибо