[原创][翻译整理]使用RAPI库操作移动设备——C#语言描述
来源:互联网 发布:linux协议栈实现分析 编辑:程序博客网 时间:2024/04/29 18:46
说明,本文原创,所有代码均摘自自己编写的程序,保证可以编译。PS, 微软的FRONTPAGE 2003还是很讨厌,自动无谓的垃圾代码,害得我光排版就花了2小时。
本页内容
● 引言 ● SMARTPHONE SDK API 库 ● 管理设备中的目录文件 ● 取系统信息 ● 远程操作电话和短信功能Windows Mobile日益成熟,开发者队伍也越来越壮大。作为一个10年的计算机热爱者和程序员,我也经受不住新技术的诱惑,倒腾起Mobile这个玩具。Mobile和Windows的血缘关系决定了它在Windows程序员中的受欢迎程度,在网络上随便搜索一下,关于Mobile应用、开发的文章数不胜数。可是对于计划开发一款全能的Desktop<=>Device同步管理程序的我来说,却发现资源少得可怜——仅仅在MSDN和两个国外的Developer网站上发现了一点资料。现在我仍然在搜索学习中,在这里把我迄今掌握的一点心得写出来,希望能起到抛砖引玉的功效。另请各位高手指正。
Mobile的开发资源很繁杂,很多人常常弄不清究竟要安装哪些工具才能搭建出合适的开发环境。但是我相信Microsoft SMARTPHONE 2003 SDK和Microsoft POCKETPC 2003 SDK是所有的人都知道的,它们分别为SmartPhone和PocketPC提供了必不可少的支持。兄弟我至今没有做出什么成绩,囊中羞涩,好容易攒了台SmartPhone,今天就已Microsoft SMARTPHONE 2003 SDK为例吧。
SMARTPHONE SDK包含了大量的API,列表如下(选自SDK文档,本人翻译):
要创建Desktop<=>Device的桌面同步管理程序,主要就依靠SDK API中的Remote API(RAPI)。RAPI 库由一组函数组成,这些函数可用于通过桌面应用程序管理设备,包括设备的目录文件、设备的注册表和系统信息。废话不多说,我们先来看看如何管理设备中的目录文件。
RAPI提供了一组文件管理的方法(不完全列表,详见SDK文档。选自SDK文档,本人翻译):
首先要说明的是,任何RAPI操作都需要首先初始化与设备的连接:
[C#.NET]
using System;using System.Runtime.InteropServices;
public class RAPI{public void RapiInit() {int ret = CeRapiInit();if( ret != 0){// 连接失败,获取失败代码int e = CeRapiGetError();// 抛出异常Marshal.ThrowExceptionForHR(ret);}// 连接成功// To Do}[DllImport("rapi.dll", CharSet=CharSet.Unicode)]internal static extern int CeRapiGetError();[DllImport("rapi.dll", CharSet=CharSet.Unicode)]internal static extern int CeRapiInit();}
连接建立后,就可以进行文件操作了。看一个将文件复制到设备的例子:
[C#.NET]
using System;using System.Runtime.InteropServices;using System.IO;
public class RAPI{private const uint GENERIC_WRITE = 0x40000000; // 设置读写权限private const short CREATE_NEW = 1; // 创建新文件private const short FILE_ATTRIBUTE_NORMAL = 0x80; // 设置文件属性private const short INVALID_HANDLE_VALUE = -1; // 错误句柄IntPtr remoteFile = IntPtr.Zero;String LocalFileName = @"c:/test.txt"; // 本地计算机文件名String RemoteFileName = @"/My Documents/test.txt"; // 远程设备文件名byte[] buffer = new byte[0x1000]; // 传输缓冲区定义为4kFileStream localFile;int bytesread = 0;int byteswritten = 0;int filepos = 0;public RapiFile() {// 创建远程文件remoteFile = CeCreateFile(RemoteFileName, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);// 检查文件是否创建成功if ((int)remoteFile == INVALID_HANDLE_VALUE){throw new Exception("Could not create remote file");}// 打开本地文件localFile = new FileStream(LocalFileName, FileMode.Open);// 读取4K字节bytesread = localFile.Read(buffer, filepos, buffer.Length);while(bytesread > 0){// 移动文件指针到已读取的位置filepos += bytesread;// 写缓冲区数据到远程设备文件if(! Convert.ToBoolean(CeWriteFile(remoteFile, buffer, bytesread, ref byteswritten, 0))){ // 检查是否成功,不成功关闭文件句柄,抛出异常CeCloseHandle(remoteFile);throw new Exception("Could not write to remote file");}try{// 重新填充本地缓冲区bytesread = localFile.Read(buffer, 0, buffer.Length);}catch(Exception){bytesread = 0;}}// 关闭本地文件localFile.Close();// 关闭远程文件CeCloseHandle(remoteFile);}
// 声明要引用的API[DllImport("rapi.dll", CharSet=CharSet.Unicode)]internal static extern int CeCloseHandle(IntPtr hObject); [DllImport("rapi.dll", CharSet=CharSet.Unicode)]internal static extern int CeWriteFile(IntPtr hFile, byte[] lpBuffer, int nNumberOfbytesToWrite, ref int lpNumberOfbytesWritten, int lpOverlapped);[DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]internal static extern IntPtr CeCreateFile(string lpFileName, uint dwDesiredAccess,int dwShareMode,int lpSecurityAttributes,int dwCreationDisposition,int dwFlagsAndAttributes,int hTemplateFile);}
操作完毕后在合适的时候需要断开RAPI连接,使用如下函数(选自SDK文档,本人翻译):
[C#.NET]
using System;using System.Runtime.InteropServices;public class RAPIUninit
{public RAPIUninit(){CeRapiUninit();}// 声明要引用的API[DllImport("rapi.dll", CharSet=CharSet.Unicode)]internal static extern int CeRapiUninit();}
文件操作的函数有很多,基本思路都是一样的,在这里就不一一举例了。请注意文件句柄使用以后一定要释放。
我们再看一个取系统信息的例子,RAPI提供了一些取系统信息的函数(选自SDK文档,本人翻译):
[C#.net]
public class RAPI{SYSTEM_INFO si;// 系统信息OSVERSIONINFO versionInfo;// 版本信息SYSTEM_POWER_STATUS_EX PowerStatus;// 电源信息MEMORYSTATUS ms;// 内存信息String info;public void systemInfo(){// 检索系统信息try{CeGetSystemInfo(out si);}catch(Exception){throw new Exception("Error retrieving system info.");}// 检索设备操作系统版本号。bool b;versionInfo.dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFO));// 设置为结构大小b = CeGetVersionEx(out versionInfo);if(!b){throw new Exception("Error retrieving version information.");}// 检索设备电源状态try{CeGetSystemPowerStatusEx(out PowerStatus, true); // true 表示读取最新的电源信息,否则将从缓存中获得}catch(Exception){throw new Exception("Error retrieving system power status.");}// 检索设备内存状态CeGlobalMemoryStatus( out ms );// 设置检索信息的格式。info = "The connected device has an ";switch (si.wProcessorArchitecture){case ProcessorArchitecture.Intel:info += "Intel processor./n";break;case ProcessorArchitecture.MIPS:info += "MIPS processor./n";break;case ProcessorArchitecture.ARM:info += "ARM processor./n";break;default:info = "unknown processor type./n";break;}info += "OS version: " + versionInfo.dwMajorVersion + "." + versionInfo.dwMinorVersion + "." +versionInfo.dwBuildNumber + "/n";if (PowerStatus.ACLineStatus == 1){info += "On AC power:YES/n";}else{info += "On AC power:NO /n";}info += "Battery level: " + PowerStatus.BatteryLifePercent + "%/n";info += "Total memory: " + String.Format("{0:###,###,###}", ms.dwTotalPhys) +"/n";// 显示结果。Console.WriteLine(info);}#region 声明API,详见SDK文档[DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]internal static extern int CeGetSystemInfo(out SYSTEM_INFO pSI);[DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]internal static extern bool CeGetVersionEx(out OSVERSIONINFO lpVersionInformation);[DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]internal static extern bool CeGetSystemPowerStatusEx(out SYSTEM_POWER_STATUS_EX pStatus, bool fUpdate);[DllImport("rapi.dll", CharSet=CharSet.Unicode, SetLastError=true)]internal static extern void CeGlobalMemoryStatus(out MEMORYSTATUS msce);#endregion#region 声明结构////// 处理器架构 (CeGetSystemInfo)///public enum ProcessorArchitecture : short{////// Intel///Intel= 0,/// /// MIPS/// MIPS= 1,////// Alpha///Alpha= 2,////// PowerPC/// PPC= 3,////// Hitachi SHx///SHX= 4,////// ARM///ARM= 5,////// IA64///IA64= 6,/// /// Alpha 64///Alpha64= 7,////// Unknown///Unknown = -1}/// /// 移动设备内存信息///[StructLayout(LayoutKind.Sequential)]public struct MEMORYSTATUS{internal uint dwLength;////// 当前内存占用 (%)///public int dwMemoryLoad;////// 物理内存总量/// public int dwTotalPhys;////// 可用物理内存///public int dwAvailPhys;/// /// 分页数///public int dwTotalPageFile;////// 未分页/// public int dwAvailPageFile;////// 虚拟内存总量/// public int dwTotalVirtual;/// /// 可用虚拟内存///public int dwAvailVirtual;}/// /// 移动设备电源信息/// public struct SYSTEM_POWER_STATUS_EX{////// 交流电状态/// public byte ACLineStatus;////// 电池充电状态。1 High,2 Low,4 Critical,8 Charging,128 No system battery,255 Unknown status///public byte BatteryFlag;////// 电池电量剩余百分比///public byte BatteryLifePercent;/// /// 保留字段,设置为0/// internal byte Reserved1;/// /// 电池电量剩余时间(秒)///public int BatteryLifeTime;////// 电池充满电的总可用时间(秒)///public int BatteryFullLifeTime;////// 保留字段,设置为0///internal byte Reserved2;/// /// 后备电池状态///public byte BackupBatteryFlag;////// 后备电池剩余电量百分比///public byte BackupBatteryLifePercent;////// 保留字段,设置为0///internal byte Reserved3;////// 后备电池电量剩余时间(秒)///public int BackupBatteryLifeTime;/// /// 后备电池充满电的总可用时间(秒)///public int BackupBatteryFullLifeTime;}/// /// OSVERSIONINFO platform type/// public enum PlatformType : int{////// Win32 on Windows CE./// VER_PLATFORM_WIN32_CE= 3}////// 操作系统版本信息/// public struct OSVERSIONINFO{internal int dwOSVersionInfoSize;////// 主版本信息/// public int dwMajorVersion;/// /// 副版本信息/// public int dwMinorVersion;/// /// 编译信息/// public int dwBuildNumber;////// 操作系统类型/// public PlatformType dwPlatformId;}/// /// 处理器类型 (CeGetSystemInfo)/// public enum ProcessorType : int{/// /// 386/// PROCESSOR_INTEL_386= 386,/// /// 486/// PROCESSOR_INTEL_486= 486,/// /// Pentium/// PROCESSOR_INTEL_PENTIUM= 586,/// /// P2/// PROCESSOR_INTEL_PENTIUMII= 686,/// /// IA 64/// PROCESSOR_INTEL_IA64= 2200,/// /// MIPS 4000 series/// PROCESSOR_MIPS_R4000 = 4000,/// /// Alpha 21064/// PROCESSOR_ALPHA_21064 = 21064,/// /// PowerPC 403/// PROCESSOR_PPC_403 = 403,/// /// PowerPC 601/// PROCESSOR_PPC_601 = 601,/// /// PowerPC 603/// PROCESSOR_PPC_603 = 603,/// /// PowerPC 604/// PROCESSOR_PPC_604 = 604,/// /// PowerPC 620/// PROCESSOR_PPC_620 = 620,/// /// Hitachi SH3///PROCESSOR_HITACHI_SH3 = 10003,/// /// Hitachi SH3E/// PROCESSOR_HITACHI_SH3E = 10004,////// Hitachi SH4/// PROCESSOR_HITACHI_SH4 = 10005,/// /// Motorola 821/// PROCESSOR_MOTOROLA_821 = 821,/// /// Hitachi SH3/// PROCESSOR_SHx_SH3 = 103,/// /// Hitachi SH4/// PROCESSOR_SHx_SH4 = 104,/// /// Intel StrongARM/// PROCESSOR_STRONGARM = 2577,/// /// ARM720/// PROCESSOR_ARM720 = 1824,/// /// ARM820/// PROCESSOR_ARM820 = 2080,/// /// ARM920/// PROCESSOR_ARM920 = 2336,/// /// ARM 7/// PROCESSOR_ARM_7TDMI = 70001}/// /// CeGetSystemInfo的数据结构/// public struct SYSTEM_INFO{/// /// 处理器架构/// public ProcessorArchitecture wProcessorArchitecture;/// /// 保留/// internal ushort wReserved;/// /// Specifies the page size and the granularity of page protection and commitment./// public int dwPageSize;/// /// 应用程序可访问内存地址的最小值///(Pointer to the lowest memory address accessible to applications/// and dynamic-link libraries (DLLs). )/// public int lpMinimumApplicationAddress;/// /// 应用程序可访问内存地址的最大值(Pointer to the highest memory address/// accessible to applications and DLLs.)/// public int lpMaximumApplicationAddress;/// /// Specifies a mask representing the set of processors configured into/// the system. Bit 0 is processor 0; bit 31 is processor 31./// public int dwActiveProcessorMask;/// /// 处理器数量(Specifies the number of processors in the system.)/// public int dwNumberOfProcessors;/// /// 处理器类型(Specifies the type of processor in the system.)/// public ProcessorType dwProcessorType;/// /// Specifies the granularity with which virtual memory is allocated./// public int dwAllocationGranularity;/// /// Specifies the system architecture-dependent processor level./// public short wProcessorLevel;/// /// Specifies an architecture-dependent processor revision./// public short wProcessorRevision;}#endregion}
RAPI可以做的事情还有很多,比如取注册表信息,提供对 Microsoft ActiveSync 底层功能的访问,运行远程应用程序,文件列表等等。只要仔细阅读SDK文档,相信都不是难事。
作为Mobile设备的桌面管理程序,备份通话记录,联机发送短信等功能是必不可少的。在我刚发现RAPI的时候,以为和前面的例子一样,有现成的函数可以使用。仔细研究以后才发现要复杂的多。相信这是很多朋友的希望实现的功能,所以班门弄斧,简述如下。
RAPI并没有提供通话,SIM卡和短信方面的函数,它们分别包含在SmartPhone SDK的Phone API,SIM Manager和Short Message Service中。然而包含这些API的phone.dll,cellcore.dll和sms.dll都是储存在设备上的,在Windows上运行的程序是无法调用存储在远程设备上的动态连接库的。
我们仍然需要RAPI。虽然它没有提供直接访问通话记录和短信方面的操作,但是它提供了一个特殊的函数:
CeRapiInvoke的原型如下:
STDAPI_( HRESULT ) CeRapiInvoke(LPCWSTR pDllPath, // 包含API的Dll文件完整路径
LPCWSTR pFunctionName, // 要调用的函数名
DWORD cbInput, // 函数输入缓冲区大小
BYTE * pInput, // 函数输入缓冲区指针
DWORD * pcbOutput, // 函数输出缓冲区大小
BYTE ** ppOutput, // 函数输出缓冲区指针
IRAPIStream ** ppIRAPIStream, // 指定使用阻塞模式或流模式
DWORD dwReserved); // 保留
CeRapiInvoke将允许我们调用远程设备中的任何API函数!不过不是直接调用,仍然需要对远程API进行一些“包装”。由于时间关系,我将在不久的将来为大家献上关于CeRapiInvoke的详细说明。
- [原创][翻译整理]使用RAPI库操作移动设备——C#语言描述
- 使用RAPI库操作移动设备——C#语言描述
- 使用RAPI库操作移动设备——C#语言描述
- 使用RAPI库操作移动设备——C#语言描述 (转贴)
- 使用RAPI库操作移动手持设备WINCE——C#语言描述
- c#调用R语言(原创翻译)
- 控制系统—自动化设备运动逻辑描述语言(1)
- 设计模式c#语言描述——建造者模式
- 设计模式c#语言描述——适配器模式
- 设计模式c#语言描述——建造者模式
- 设计模式c#语言描述——适配器模式
- 【原创-翻译】C#编码规范
- IOS开发系列——设备信息专题【整理,部分原创】
- Rapi
- RAPI
- C#使用OpenNETCF.Desktop.Communication,实现对ActiveSync状态的判断,及对移动设备文件的操作!
- 原创翻译 使用Windows Embedded Standard创建电池供电的设备(一)
- 原创翻译 使用Windows Embedded Standard开发电池供电设备(二)
- Java游戏编程---人机交互和用户接口
- 用智能ABC关闭程序
- 赋值操作符与关系操作符的优先级
- ---" ~ " 的用法---
- 给中国学生的第四封信:大学四年应是这样度过 by 李开复
- [原创][翻译整理]使用RAPI库操作移动设备——C#语言描述
- 2005年6月5日 晴 今天是星期日
- 365key对外合作方案
- (转载)考研数学满分(150分)的独家经验
- 三种地理信息辅助路由协议分析
- Linux编程学习三
- 怎么每天都有人去自杀
- OpenGL开发工具
- 黄页是什么意思