如何通过Windows Mobile 6使用存储管理器API格式化SD卡

16

背景:

我正在尝试创建一个实用工具,让我们的客户可以直接在Windows Mobile 6设备(Intermec CK3)上轻松格式化SD卡(实际上是mini-SD)。这比使用第三方工具如FlashFormat或为客户提供读卡器更可取(这将需要他们拆下电池,拉出由脆弱金属外壳固定的mini-SD卡,然后通过文件管理控制运行Windows格式化实用程序)。我们大部分的客户并不是很精通技术,因此一个可以自动运行或只需几次点击即可运行的工具是理想的。

我已经尝试了以下方式:

  • 查看这个问题。这里的答案似乎不适用于Windows Mobile(例如没有WMI支持或format.com实用程序)。
  • 尝试使用CreateFileDeviceIoControlCE。这个方法看起来很有前途,但是SD卡似乎永远无法真正格式化。据我所知,这是因为首先需要卸载该卡。
  • 尝试使用CreatFileFormatVolumeEx(以及其他变体,如FormatVolumeFormateVolumeUI)。结果似乎类似,除非首先卸载卡片,否则无法格式化该卡。

在进行了一些搜索并遇到此主题(由paraGOD在底部回答),以及这篇博客之后,我决定采用使用存储管理器 API的新路径,该API具有FindFirstStoreFindNextStoreOpenStoreDismountStore等函数。

我正在尝试使用C#进行此操作,因此我创建了必要的支持结构来表示API中使用的typedefs。这是一个示例:

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;
    }
}

接着,我创建了一个静态存储管理器类来保存所有存储管理器函数(应该在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

因此,我去测试了一些这些函数,例如通过FindFirstStore和FindNextStore函数枚举商店,然后我遇到了可怕的“在PInvoke DLL 'Coredll.dll'中找不到条目点“ FindFirstStore”错误(在调试器输出中,我还得到了“SDFormatter.exe”的类型为'System.MissingMethodException'的第一次机会异常,这是有意义的)。更多的研究表明,在Windows Mobile中,尽管它们是Coredll的一部分,但这些功能并未公开。但是它们是Windows CE 6的一部分,并可以通过平台构建器访问。

因此,这里是我主要的问题:

  • 我是否可以以某种方式通过C#访问Windows Mobile 6中的Storage Manager API?
  • 如果不行,是否可以通过托管的C ++编写实用程序(我不太懂,但如果必要,我会摸索过去),但不必使用平台构建器(它不免费)?
  • 如果只能通过平台构建器实现,那么这是否意味着我要么被困在构建自己的SDK中,要么必须要求Intermec为我公开功能?

如果有人有建议,我也很愿意从完全另一个角度解决这个问题(最好是通过C#)。我想也许让客户将设备安装在底座上并运行桌面实用程序是一个好方法。不确定这是否可行,并且它不能依赖于ActiveSync(我们不想支持另一个工具,因此我们通过连接到插座的网络适配器通过套接字在自定义服务器程序和我们的移动应用程序之间进行通信来发送数据到和从SD卡)。

谢谢


我发现了一个可能相关的2009年新闻组帖子:http://www.pocketpcjunkies.com/Uwe/Forum.aspx/wince-pb/21443/StoreApi-Lib-not-exported-in-the-SDK-and-linking-di-rect-doesn - PaulH
2个回答

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);
}

0

FindFirstStore在Windows Mobile 5.0及以后的设备中可以在公共API中使用,所以你不需要像平台构建器那样使用任何高端工具。

我记得我在某个地方读到,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;
}

我明天会尝试一下这个(可能要等到周三),然后告诉你进展如何。谢谢你的建议。 - Jason Down
几天前,当我看到这个问题时,我尝试使用本机代码构建类似的东西,但它无法链接,因为WinMo SDK(5.0和6.0)不包括storeapi.lib。我还检查了coredll,但没有发现任何内容。 - ctacke
问题在于WinMo中不存在storeapi.dll(至少在5.0或6.5模拟器上没有),而coredll.lib的定义也不包含存储API入口点。 - ctacke
PaulH和@ctacke:这个项目在优先级列表上被打倒了,所以我从来没有机会测试它。下周看起来很适合我回去处理它。如果对我有效,我会告诉你们的。 - Jason Down
如果需要的话,可以下载平台构建器评估版。它包含了共享源代码。https://www.microsoft.com/download/en/details.aspx?id=20083 如果您不想在30天后被骚扰,可以复制我们的源代码并卸载它。 - PaulH
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接