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