Как отформатировать SD-карту с помощью Storage Manager API через Windows Mobile 6

Задний план:

Я пытаюсь создать утилиту, которая позволит нашим клиентам легко форматировать 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 , что имеет смысл). Еще одно исследование показало, что в Windows Mobile эти функции не доступны, хотя они являются частью Coredll. Однако они являются частью Windows CE 6 и могут быть доступны через конструктор платформы.

Итак, вот основные вопросы, которые у меня есть:

  • Могу ли я каким-то образом получить доступ к Storage Manager API через C # в Windows Mobile 6?
  • Если нет, могу ли я написать утилиту через управляемый C ++ (я мало что знаю, но при необходимости наткнусь на нее), но без использования конструктора платформ (это не бесплатно)?
  • Если это возможно только через конструктор платформ, означает ли это, что я либо застрял в создании собственного SDK, либо мне придется попросить Intermec предоставить мне эту функциональность?

Я также открыт для того, чтобы сделать это совершенно другим способом (предпочтительно через C #), если у кого-то есть предложения. Я подумал, может быть, заказчик установит устройство в подставку и запустит настольную утилиту. Не уверен, возможно ли это, и он не может полагаться на ActiveSync (мы не хотим поддерживать еще один инструмент, поэтому мы отправляем данные на SD-карту и с нее через сетевой адаптер, подключенный к подставке, используя разъемы для разговора между нашими кастомная серверная программа и наше мобильное приложение).

Спасибо


person Jason Down    schedule 24.08.2011    source источник
comment
Я наткнулся на эту ветку группы новостей 2009 года, которая может быть актуальной: pocketpcjunkies.com/Uwe/Forum.aspx/wince-pb/21443/   -  person PaulH    schedule 29.08.2011


Ответы (2)


У нас было точно такое же требование, но на Windows CE. Нашим решением было создание небольшого приложения на C ++, которое затем вызывается из кода C #. Вот самая важная часть приложения 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);
}
person ollifant    schedule 04.02.2012

FindFirstStore доступен на устройствах с Windows Mobile 5.0 и более поздних версий в общедоступном API, так что вам не понадобится ничего особенного, вроде конструктора платформ.

Кажется, я где-то читал, что FindFirstStore был перемещен только в coredll.dll в CE6 (я не помню, где я это видел). Итак, ваше устройство Windows Mobile 6, вероятно, будет экспортировано откуда-то еще. (возможно storeapi.dll?)

Попробуйте создать проект на C ++ с помощью этого кода и посмотрите, подойдет ли он вам:

#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;
}
person PaulH    schedule 29.08.2011
comment
Я займусь этим завтра (возможно, придется подождать до среды) и расскажу, как все пойдет. Спасибо за предложение. - person Jason Down; 29.08.2011
comment
Я попытался создать что-то подобное в машинном коде несколько дней назад, когда увидел этот вопрос, но он не может быть связан, потому что WinMo SDK (5.0 и 6.0) не включает storeapi.lib. Я также проверил coredll и ничего не нашел. - person ctacke; 30.08.2011
comment
@ctacke - Я только что вернулся к своему компьютеру, чтобы попробовать это сам. Вы правы. storeapi.lib является частью исходных текстов Windows Mobile, включенных в конструктор платформы. PUBLIC\COMMON\OAK\LIB\ARMV4I\RETAIL\storeapi.lib. Если вы знаете способ получить порядковый номер из библиотеки импорта, я поищу его, и он сможет импортировать функции по порядковому номеру. - person PaulH; 30.08.2011
comment
Проблема в том, что storeapi.dll не существует в WinMo (по крайней мере, в эмуляторах 5.0 или 6.5), а определение coredll.lib не содержит точек входа API магазина. - person ctacke; 30.08.2011
comment
Я только что запустил опубликованный код, и он работает в Windows Mobile 6.5.3. Отладчик показывает, что он загружает ресурсы из coredll.dll и ничего больше. Я предполагаю, что это означает, что он экспортируется только по порядковому номеру из coredll. - person PaulH; 30.08.2011
comment
PaulH и @ctacke: Этот проект попал в список приоритетов, поэтому у меня не было возможности его протестировать. На следующей неделе я надеюсь вернуться к этому. Я дам вам знать, если это сработает для меня. - person Jason Down; 16.09.2011
comment
Если вам это нужно, скачайте ознакомительную версию конструктора платформ. Имеет общие источники. microsoft.com/download/en/details.aspx?id=20083 Вы можете скопировать наш исходный код и удалить его, если не хотите, чтобы вас беспокоили через 30 дней. - person PaulH; 16.09.2011