以前查找了好些在.net CF框架上调用设备本地API函数读取手机SIM卡的资料,但各种资料都少了些描述,特别是少了一些引用的结构(struct),造成了资料中的原代码不能直接运行,让很多学习的朋友遇到很多麻烦,花费了多余的时间,走了一些弯路。
我也遇到了类似的问题,通过补充了一些缺失的代码后,使程序可以正常的读取SIM卡了。
SIM 卡
Pocket PC Phone 的内置电话功能使它成为移动电话家族的重要成员,在创建新的连接应用程序时,可以利用该功能。与所有移动电话一样,Pocket PC 电话也需要用户身份模块 (SIM) 卡才能拨打电话(紧急电话除外,拨打紧急电话时无需 SIM 卡)。例如,连接应用程序可以通过在启动连接之前检查用户的个人识别码 (PIN) 代码来利用 SIM 卡的安全功能。
SIM 卡可以存储移动电话的电话号码以及提供此号码的操作员的身份标识。另外,它还可以存储附加有姓名的电话号码以及多条短消息服务的消息。SIM 卡不仅具有存储器,还具有使卡可以进行安全和加密处理的中央处理器。通常情况下,您需要使用 PIN 代码“登录”到 SIM 卡。
SIM 管理器 API
在 Pocket PC Phone 中,您可以使用一系列 Windows CE API 调用(统称为 SIM 管理器)来访问 SIM 卡上的信息。
会话以调用 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 的原型,该示例需要以下原型:
public const int SIM_PBSTORAGE_SIM = 0x10; //
public const int SIM_SMSSTORAGE_SIM = 0x2; //
[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);
[DllImport("cellcore.dll")]
public static extern int SimReadPhonebookEntry(int hSim, uint dwLocation, uint dwIndex, ref SIMPHONEBOOKENTRY entry);
[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;
}
//很多文章都缺失的结构
[StructLayout(LayoutKind.Sequential)]
public struct SimLockingPwdLength
{
public uint dwFacility;
public uint dwPasswordLength;
}
//很多文章都缺失的结构
[StructLayout(LayoutKind.Sequential)]
public struct SIMPHONEBOOKENTRY
{
public uint cbSize; //
public uint dwParams; //
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string lpszAddress; // 联系人电话
public uint dwAddressType; //
public uint dwNumPlan; //
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string lpszText; // 联系人姓名
}
/// <summary>
/// 获取SIM卡联系人信息
/// </summary>
/// <returns></returns>
public static List<string[]> GetSIMContactList()
{
int hSim = 0;
List<string[]> list = new List<string[]>();
try
{
int result = SimInitialize(0, 0, 0, ref hSim);
if (result != 0)
throw new Exception("SIM打卡失败,请检测SIM是否安装!");
uint uiUsed = 0;
uint uiTotal = 0;
result = SimGetPhonebookStatus(hSim, SIM_PBSTORAGE_SIM, ref uiUsed, ref uiTotal);
for (int i = 1; i <= uiUsed; i++)
{
SIMPHONEBOOKENTRY entry = new SIMPHONEBOOKENTRY();
entry.cbSize = (uint)Marshal.SizeOf(typeof(SIMPHONEBOOKENTRY));
result = SimReadPhonebookEntry(hSim, SIM_PBSTORAGE_SIM, (uint)i, ref entry);
list.Add(new string[2] { entry.lpszText.Trim(), entry.lpszAddress.Trim() });
}
return list;
}
catch
{
throw;
}
finally
{
SimDeinitialize(hSim);
}
}
声明适当时,“获取 SIM 信息”按钮所表示的代码如下所示:
dataGrid1为列表控件
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("姓名", typeof(string)));
dt.Columns.Add(new DataColumn("号码", typeof(string)));
string[] str;
for(int i = 0; i < list.Count; i++)
{
str = list[i];
DataRow dr = dt.NewRow();
dr[0] = str[0].ToString();
dr[1] = str[1].ToString();
dt.Rows.Add(dr);
}
dataGrid1.DataSource = dt;
小结
由于 Pocket PC Phone 是移动电话家族的重要成员,因此在创建大型的连接应用程序时可以利用其功能,例如 SIM 卡。使用 SIM 管理器 API、Compact Framework 的 Interop 服务以及 .NET 开发环境,可以获得实现这一功能的工具。