背景:
我正在尝试创建一个实用程序,允许我们的客户直接在 Windows Mobile 6 设备 (Intermec CK3) 上轻松格式化 SD 卡(实际上是 mini-SD)。这将优于第三方工具,例如FlashFormat或必须向客户提供读卡器(这将要求他们卸下电池,拉出由脆弱的金属外壳固定的 mini-SD 卡,然后通过文件管理控件运行 Windows 格式化实用程序)。我们的大多数客户都不是很精通技术,因此可以自动运行或通过几次单击运行的实用程序将是理想的选择。
到目前为止,我已经尝试了以下方法:
- 看了这个问题。此处的答案似乎不适用于 Windows Mobile(例如,不支持 WMI 或 format.com 实用程序)。
- 尝试使用CreateFile和DeviceIoControlCE。这个看起来很有希望,但 SD 卡似乎永远不会真正格式化。据我所知,这是因为需要先卸下卡。
- 尝试使用CreatFile和FormatVolumeEx(以及其他变体FormatVolume和FormateVolumeUI)。结果似乎是相似的,除非先将其卸下,否则我无法格式化该卡。
在搜索了这个线程(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;
}
}
然后我创建了一个静态存储管理器类来保存所有存储管理器功能(应该在 coredll for 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 函数简单地枚举存储然后我得到可怕的,在 PInvoke DLL 'Coredll.dll'错误中找不到入口点'FindFirstStore'(在调试器输出中,我还得到了 SDFormatter.exe 中发生的“System.MissingMethodException”类型的第一次机会异常,这是有道理的)。更多研究表明,在 Windows Mobile 中,这些功能并未公开,即使它们是 Coredll 的一部分。然而,它们是 Windows CE 6 的一部分,可以通过平台构建器访问。
所以这是我的主要问题:
- 我可以通过 Windows Mobile 6 中的 C# 以某种方式访问 Storage Manager API 吗?
- 如果不是,我可以通过托管 C++ 编写一个实用程序(我不太了解,但如果有必要我会偶然发现它),但不必使用平台构建器(它不是免费的)?
- 如果只能通过平台构建器实现,这是否意味着我要么被困在构建自己的 SDK 中,要么必须要求 Intermec 为我公开该功能?
如果有人有建议,我也愿意完全以另一种方式(最好是通过 C#)这样做。我在想也许让客户将设备安装在底座上并运行桌面实用程序。不确定这是否可能并且它不能依赖 ActiveSync(我们不想支持另一个工具,所以我们通过连接到底座的网络适配器向 SD 卡发送数据和从 SD 卡发送数据,使用套接字在我们的自定义服务器程序和我们的移动应用程序)。
谢谢