如何通过Windows Mobile 6使用Storage Manager API格式化SD卡

Jas*_*own 16 c# compact-framework windows-mobile windows-mobile-6

背景:

我正在尝试创建一个实用程序,允许我们的客户直接在Windows Mobile 6设备(Intermec CK3)上轻松格式化SD卡(实际上是mini-SD).这将优于FlashFormat等第三方工具或必须向客户提供读卡器(这将要求他们取出电池,拔出由脆弱的金属外壳固定的mini-SD卡,然后通过文件管理控件运行Windows格式化实用程序).我们的大多数客户都不是非常精通技术,因此可以自动运行或通过几次点击运行的实用程序将是理想的选择.

到目前为止我已尝试过以下内容:

  • 看着这个问题.这里的答案似乎不适用于Windows Mobile(例如没有WMI支持或format.com实用程序).
  • 尝试使用CreateFileDeviceIoControlCE.这个看起来很有希望,但SD卡似乎永远不会真正格式化.据我所知,这是因为卡需要首先卸下.
  • 尝试使用CreatFileFormatVolumeEx(以及其他变体,FormatVolumeFormateVolumeUI).结果似乎是相似的,因为我不能格式化卡,除非它首先被拆除.

在做了一些搜索到这个线程(在paraGOD附近回答)和这个博客之后,我决定走下一条使用Store Manager API的新路径,它具有FindFirstStore,FindNextStore,OpenStore,DismountStore等功能. .

我正在尝试在C#中执行此操作,因此我创建了必要的支持结构来表示API中使用的typdef.这是一个样本:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个静态存储管理器类来保存所有存储管理器功能(它们应该在用于Windows Mobile 6的coredll中可用......或者我认为是这样):

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
Run Code Online (Sandbox Code Playgroud)

所以我去测试其中的一些功能,比如简单地通过FindFirstStore和FindNextStore函数枚举存储然后我得到了可怕的,无法在PInvoke DLL中找到入口点'FindFirstStore''Coredll.dll'错误(在调试器输出中我也得到了SDFormatter.exe中发生的'System.MissingMethodException'类型的第一次机会异常,这是有道理的).一些更多的研究暗示,在Windows Mobile中,即使它们是Coredll的一部分,也不会暴露这些功能.但它们是Windows CE 6的一部分,可以通过平台构建器访问.

以下是我的主要问题:

  • 我可以通过Windows Mobile 6中的C#访问Storage Manager API吗?
  • 如果没有,我可以通过托管C++编写一个实用程序(我不太了解,但如果有必要我会偶然发现它),但不必使用平台构建器(它不是免费的)?
  • 如果只能通过平台构建器,这是否意味着我要么自己构建自己的SDK,要么让Intermec为我公开这些功能?

如果有人有建议,我也愿意完全这样做(最好通过C#).我想也许让客户将设备安装在底座上并运行桌面实用程序.不确定这是否可行并且不能依赖ActiveSync(我们不想再支持其他工具,所以我们通过连接到底座的网络适配器使用套接字在SD卡之间发送数据,以便在我们之间进行通信自定义服务器程序和我们的移动应用程序

谢谢

Pau*_*ulH 0

FindFirstStore可通过公共 API 在 Windows Mobile 5.0 及更高版本的设备上使用,因此您不需要像平台构建器这样的任何花哨的东西。

我想我在某处读到,FindFirstStore 在 CE6 中仅被移至 coredll.dll(我不记得在哪里看到过)。因此,您的 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;
}
Run Code Online (Sandbox Code Playgroud)