摘要:学习如何使用 SIM 治理器 API、Compact Framework 的 Interop 服务以及 .NET 开发环境来创建用于 Pocket PC Phone 的连接应用程序。(本文还包含英文链接。)
下载 sim_PRogramming.exe
SIM 卡
Pocket PC Phone 的内置电话功能使它成为移动电话家族的重要成员,在创建新的连接应用程序时,可以利用该功能。与所有移动电话一样,Pocket PC 电话也需要用户身份模块 (SIM) 卡才能拨打电话(紧急电话除外,拨打紧急电话时无需 SIM 卡)。例如,连接应用程序可以通过在启动连接之前检查用户的个人识别码 (PIN) 代码来利用 SIM 卡的安全功能。
SIM 卡可以存储移动电话的电话号码以及提供此号码的操作员的身份标识。另外,它还可以存储附加有姓名的电话号码以及多条短消息服务的消息。SIM 卡不仅具有存储器,还具有使卡可以进行安全和加密处理的中心处理器。通常情况下,您需要使用 PIN 代码“登录”到 SIM 卡。
SIM 治理器 API
在 Pocket PC Phone 中,您可以使用一系列 Windows CE API 调用(统称为 SIM 治理器)来访问 SIM 卡上的信息。以下为 SIM 治理器 API(按功能分组):
表 1:SIM 治理器 API
会话以调用 SimInitialize 开始,这将返回一个 SIM 句柄,此后,在调用 SIM 治理器 API 函数时均需要此句柄。通过将此句柄传递给 SimDeinitialize 来终止会话。使用 Compact Framework 调用 Windows API
使用 SDE (Smart Device Extensions) 和 Compact Framework,可以进行 Microsoft? Windows? API 调用,例如使用 Interop(erability) 服务访问 SIM 治理器 API。
SIM Anyplace 示例
该示例是使用 Microsoft Visual Studio? .NET、C#、SDE 和 .NET CF 创建的 Pocket PC Phone 的示例应用程序。它展示了如何使用 SIM 治理器 API 访问 SIM 卡。该应用程序包含一个窗体:
此示例的用途仅限于通过敲击“获取 SIM 信息”按钮从 SIM 卡获取一般信息。但是,通过使用此示例的结构可以将其用途扩展至包含更多的 SIM 治理器 API 功能。
代码演练
要使用 Compact Framework 的 Interop 服务,需要添加以下代码:
using System.Runtime.InteropServices;
创建类 SIMWrap 来存储 Windows API 的原型,该示例需要以下原型:
[DllImport("cellcore.dll")]
public static extern int SimInitialize(uint dwFlags,
int lpfnCallBack, uint dwParam, ref int lphSim);
[DllImport("cellcore.dll")]
public static extern int SimGetPhonebookStatus(int hSim,
uint dwLocation, ref uint lpdwUsed, ref uint lpdwTotal);
[DllImport("cellcore.dll")]
public static extern int SimGetDevCaps(int hSim,
uint dwCapsType, ref SimCaps lpSimCaps);
[DllImport("cellcore.dll")]
public static extern int SimGetSmsStorageStatus(int hSim,
uint dwStorage, ref uint lpdwUsed, ref uint lpdwTotal );
[DllImport("cellcore.dll")]
public static extern int SimDeinitialize(int hSim);
每个原型均具有一个指向 DLL(动态链接库,在其中执行函数)的 DllImport 属性,在本例中为 cellcore.dll。创建这些原型时,Visual Studio .NET 帮助文件提供了一个包含类型映射的极好表格(请在索引中查找“平台调用”和“数据类型”)。例如,本地类型“DWord”映射到治理类型“UInt32”,UInt32 为 C# 中的一个“单位”。
用于获取 SIM 卡功能的调用 (SimGetDevCaps) 包含一个由引用 (lpSimCaps) 作为最后参数传递的结构。本地 (C++) 结构如下所示:
typedef strUCt simcaps_tag {
DWORD cbSize;
DWORD dwParams;
DWORD dwPBStorages;
DWORD dwMinPBIndex;
DWORD dwMaXPBIndex;
DWORD dwMaxPBEAddressLength;
DWORD dwMaxPBETextLength;
DWORD dwLockFacilities;
DWORD dwReadMsgStorages;
DWORD dwWriteMsgStorages;
DWORD dwNumLockingPwdLengths;
SIMLOCKINGPWDLENGTH rgLockingPwdLengths[SIM_NUMLOCKFACILITIES];
} SIMCAPS, FAR *LPSIMCAPS;
当 SIM_NUMLOCKFACILITIES 等于 10 时,相同结构的 Compact Framework 版本如下所示:
[StructLayout(LayoutKind.Sequential)]
public struct SimCaps
{
public uint cbSize;
public uint dwParams;
public uint dwPBStorages;
public uint dwMinPBIndex;
public uint dwMaxPBIndex;
public uint dwMaxPBEAddressLength;
public uint dwMaxPBETextLength;
public uint dwLockFacilities;
public uint dwReadMsgStorages;
public uint dwWriteMsgStorages;
public uint dwNumLockingPwdLengths;
public SimLockingPwdLength rgLockingPwdLengths0;
public SimLockingPwdLength rgLockingPwdLengths1;
public SimLockingPwdLength rgLockingPwdLengths2;
public SimLockingPwdLength rgLockingPwdLengths3;
public SimLockingPwdLength rgLockingPwdLengths4;
public SimLockingPwdLength rgLockingPwdLengths5;
public SimLockingPwdLength rgLockingPwdLengths6;
public SimLockingPwdLength rgLockingPwdLengths7;
public SimLockingPwdLength rgLockingPwdLengths8;
public SimLockingPwdLength rgLockingPwdLengths9;
}
请注重,即使 MarchalAsAttribute 类在 Compact Framework (Beta 1) 中不受支持,通过使用附加后缀 (0-9) 将阵列添加为成员几乎可以实现相同的结构。实际上,这些成员属于另一种结构 (SimLockingPwdLength)。
声明适当时,“获取 SIM 信息”按钮所表示的代码如下所示:
SimWrap.SimCaps simCaps = new SimWrap.SimCaps();
int hSim = 0;
uint phoneUsed = 0;
uint phoneTotal = 0;
uint smsUsed = 0;
uint smsTotal = 0;
// 清空 ListView
lvwItems.Items.Clear();
// 启动 SIM 治理器会话(获取句柄)
SimWrap.SimInitialize(0, 0, 0, ref hSim);
// 获取电话簿状态(使用部分、全部)
SimWrap.SimGetPhonebookStatus(hSim, SimWrap.SIM_PBSTORAGE_SIM,
ref phoneUsed, ref phoneTotal);
AddToListView("Total phonebook size:", phoneTotal.ToString());
AddToListView("Phonebook entries:", phoneUsed.ToString());
// 获取 SIM 功能
SimWrap.SimGetDevCaps(hSim, SimWrap.SIM_CAPSTYPE_ALL, ref simCaps);
AddToListView("Max. length of name:",
simCaps.dwMaxPBETextLength.ToString());
AddToListView("Max. length of phone number:",
simCaps.dwMaxPBEAddressLength.ToString());
// 获取消息 (SMS) 状态(使用部分、全部)
SimWrap.SimGetSmsStorageStatus(hSim, SimWrap.SIM_SMSSTORAGE_SIM,
ref smsUsed, ref smsTotal);
AddToListView("SMS message storage capacity:", smsTotal.ToString());
AddToListView("SMS messages:", smsUsed.ToString());
// 结束 SIM 治理器会话
SimWrap.SimDeinitialize(hSim);
清空 ListView 且检索 (SimInitialize) 到 SIM 治理器句柄 (hSim) 后,将调用 SIM Wrapper 类 (SimWrap) 上的每个静态方法,从而产生 API 调用。作为引用传递的变量将获取返回值,并使用代码将其添加至 ListView 中。
private void AddToListView(string Item, string Value)
{
ListViewItem lvi = new ListViewItem(Item);
lvi.SubItems.Add(Value);
lvwItems.Items.Add(lvi);
}
最后,在调用 SimDeinitialize 时将释放 SIM 治理器句柄 (hSim)。
小结
由于 Pocket PC Phone 是移动电话家族的重要成员,因此在创建大型的连接应用程序时可以利用其功能,例如 SIM 卡。使用 SIM 治理器 API、Compact Framework 的 Interop 服务以及 .NET 开发环境,可以获得实现这一功能的工具。