使用RAPI库操作移动设备——C#语言描述

使用RAPI库操作移动设备——C#语言描述

WINCE和Winows Mobile的开发资源很繁杂,很多人常常弄不清究竟要安装哪些工具才能搭建出合适的开发环境。但是我相信Microsoft SMARTPHONE 2003 SDK和Microsoft POCKETPC 2003 SDK是所有的人都知道的,它们分别为SmartPhone和PocketPC提供了必不可少的支持。以Microsoft SMARTPHONE 2003 SDK为例吧。

SMARTPHONE SDK包含了大量的API,列表如下(选自SDK文档):


Smartphone API


Description


ActiveSync


创建移动应用程序安装和配置,同步服务模块,过滤器和协助访问ActiveSync服务的应用。


Bluetooth API


创建支持蓝牙设备的Mobile应用程序,比如耳机,打印机和其他移动设备。


CE Messaging (CEMAPI)


创建messaging applications


Configuration Service Providers


创建可配置各种CSPs(Configuration Service Providers)的应用


Connection Manager


创建可自动管理移动设备网络连接的应用


Control API


在你的移动应用程序中使用Smartphone控件


Device Management API


创建可远程访问移动设备配置管理的应用程序


Game API (GAPI)


创建高性能的实时游戏


Home Screen API


创建用户界面插件


HTML Control


创建可显示HTML文本和嵌入图片,解析XML和绑定URL到别名的应用程序


MIDI


创建可播放MIDI文件的应用程序


Object Exchange (OBEX)


创建对象交换应用,允许移动设备自由的通过无线交换数据


Pocket Outlook Object Model (POOM) API


创建可操作收件箱部件(联系人,日历和任务)的移动应用程序


Projects Control


创建可以和Projects Control交互的应用


Remote API (RAPI)


创建可以同步或控制移动设备的桌面应用程序


Speech Recognizer


为应用程序增加语音识别功能(比如语音拨号)


Telephony


创建支持电话和短信的应用程序


User Interface


管理输入面板,增加用户界面元素到你的移动应用程序


Vibrate API


为你的移动应用程序增加震动特性


Voice Recorder Control


创建移动数字录音程序


Windows User Interface Controls


创建将移动扩展合并到标准Microsoft? Windows? CE用户界面控件的应用

要创建Desktop<=>Device的桌面同步管理程序,主要就依靠SDK API中的Remote API(RAPI)。RAPI 库由一组函数组成,这些函数可用于通过桌面应用程序管理设备,包括设备的目录文件、设备的注册表和系统信息。废话不多说,我们先来看看如何管理设备中的目录文件

RAPI提供了一组文件管理的方法(不完全列表,详见SDK文档。):


Function


Description


CeCopyFile


复制文件


CeCreateDirectory


创建目录


CeCreateFile


创建,打开文件、管道、通讯资源、磁盘设备或者控制台。返回一个句柄用来访问对象。


CeDeleteFile


删除文件


CeFindAllFiles


从指定的Windows CE目录中获取所有文件和目录的信息,并且复制到一个包含CE_FIND_DATA结构的数组中


CeFindFirstFile


在目录中查找匹配给定文件名的一个文件


CeFindClose


关闭指定的查找句柄,CeFindFirstFile和CeFindNextFile 函数用这个句柄查找文件


CeFindNextFile


从上一次访问的CeFindFirstFile继续查找文件


CeGetFileAttributes


返回指定文件或目录的属性


CeGetFileSize


获取指定文件的字节大小


CeGetFileTime


获取文件创建日期时间,最后访问日期时间和最后修改日期时间


CeMoveFile


移动(重命名)一个文件或者目录


CeReadFile


从文件指针处读取文件数据


CeWriteFile


从文件指针处写入文件数据

首先要说明的是,任何RAPI操作都需要首先初始化与设备的连接:


Function


Description


CeRapiInit (RAPI)


创建Windows CE remote application-programming interface (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];    // 传输缓冲区定义为4k

FileStream 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文档):


Function


Description


CeRapiUninit (RAPI)


销毁Windows CE remote application-programming interface (RAPI).


[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文档,本人翻译):


Function


Description


CeGetSystemInfo


返回当前系统信息


CeGetSystemMetrics


获取Windows元素的尺寸和系统设置


CeGetVersionEx


获取当前运行的操作系统版本的扩展信息


CeGetSystemPowerStatusEx


获取电池状态


CeGlobalMemoryStatus


获取系统物理内存和虚拟内存信息


CeGetStoreInformation


获取存储器信息并填入STORE_INFORMATION结构


[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。虽然它没有提供直接访问通话记录和短信方面的操作,但是它提供了一个特殊的函数:


Function


Description


CeRapiInvoke


使用一种通用的机制执行远程程序

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的详细说明。

时间: 2024-10-11 04:55:20

使用RAPI库操作移动设备——C#语言描述的相关文章

第八章|MySQL数据库|库操作|表操作

1.初识数据库 我们在编写任何程序之前,都需要事先写好基于网络操作一台主机上文件的程序(socket服务端与客户端程序),于是有人将此类程序写成一个 专门的处理软件,这就是mysql等数据库管理软件的由来,但mysql解决的不仅仅是数据共享的问题,还有查询效率,安全性等一系列问题, 总之,把程序员从数据管理中解脱出来,专注于自己的程序逻辑的编写. 数据(Data):描述事物的符号记录称为数据,描述事物的符号既可以是数字,也可以是文字.图片,图像.声音.语言等,数据由多种表现形式,它们都可以经过数

mysql基本认识【关系型数据库和nosql、mysql操作流程和体系,库操作,表操作,数据的操作,字符集的操作,以及php作为client操作数据库】对连接本身没有疑问

1.关系型数据库永久性保存数据的仓库php的变量只是php脚本执行期间,临时性保存变量的空间[使用内存空间临时保存] 关系型数据库:利用二者的关系来描述实体的信息.[利用二维表字段名和字段值来进行描述][关系型数据库根本不是可以使用外键将两个表构建成关联的意思,而是实现描述实体的二维表的形式] nosql:not only sql[sql表示操作关系型数据的语言]所以nosql指的就是非关系型数据库[典型的是键值对型的数据(redis.memcache)][nosql可以视情况添加信息,不需要对

Python 3 mysql 库操作

Python 3 mysql 库操作 一.基础相关知识 MySQL数据库基本操作知识储备 数据库服务器:一台计算机(对内存要求比较高) 数据库管理系统:如mysql,是一个软件 数据库:oldboy_stu,相当于文件夹 表:student,scholl,class_list,相当于一个具体的文件 记录:1 刘海龙 324245234 22,相当于文件中的一行内容 二.SQL语言简介 SQL(Structured Query Language 即结构化查询语言) SQL语言主要用于存取数据.查询

php笔记08:数据库编程---使用php的MySQL扩展库操作MySQL数据库

1.使用php的MySQL扩展库操作MySQL数据库: php有3种方式操作MySQL数据库 (1)mysql扩展库 (2)mysqli扩展库 (3)pdo   mysql扩展库与mysql数据库区别 ? php设计者封装了一些方法去操作mysql数据库,这些方法集中起来形成了mysql扩展库.mysql数据库存放数据.     2.使用php的MySQL扩展库操作MySQL数据库案例: (1)环境搭建:启用MySQL数据库,在php.ini文件中配置使用MySQL数据库,          

MySQL数据库:SQL语句基础、库操作、表操作、数据类型、约束条件、表之间的关系

数据库相关概念: 1. 数据库服务器:运行数据库管理软件的计算机 2. 数据库管理软件:MySQL.Oracle.db2.slqserver 3. 库:文件夹,用来组织文件/表 4. 表:文件(类似于excel),用来存放多行内容/多条记录 5. 记录:事物一系列典型的特征 6. 数据:描述事物特征的符号 MySQL数据库就是一个套接字软件,用来管理其他机器上的数据文件 MySQL介绍: MySQL是一个关系型数据库管理系统:就是一个基于socket编写的C/S架构胡软件 客户端软件 mysql

DDL-数据库操作、 DML数据操作

DDL之数据库操作:database 创建数据库 格式: create database 数据库名; create database 数据库名 character set 字符集; #创建数据库 数据库中数据的编码采用的是安装数据库时指定的默认编码 utf8 create database webdb_1; #创建数据库 并指定数据库中数据的编码 create database webdb_2 character set utf8; 查看数据库 查看数据库MySQL服务器中的所有的数据库: sh

IO库中的宽字符语言

wchar_t是C/C++的字符类型,是一种扩展的存储方式.wchar_t类型主要用在国际化程序的实现中,但它不等同于uni编码.uni编码的字符一般以wchar_t类型存. IO库为了支持宽字符语言,定义了一组类型和对象来操作wchar_t类型.例如:wcin,wcout,wcerr;以及如下图头文件: #include <iostream> using namespace std; int main() { wchar_t wStr[]=L"ABCDEFG"; char

Dataguard搭建灾备库操作手册

数据库:Oracle11gr2 主库 alter database force logging; alter system set db_unique_name='erpdb' scope=spfile;  --我们让主库db_name=db_unique_name alter system set REMOTE_LOGIN_PASSWORDFILE=EXCLUSIVE scope=spfile; alter system set LOG_ARCHIVE_FORMAT='%t_%s_%r.arc

Win10 IoT C#开发 5 - 操作 IoT 设备内嵌 SQLite 数据库 CURD

Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 前几章我们讲了 Raspberry 安装 Win10 IoT 系统及搭建开发环境.部署程序及操作 GPIO 和 UART 的方法,通过这些功能我们已经可以获得到传感器发送给我们的数据,但是如果数据不能及时推送回服务器就需要在本地缓存,使用 SQLite 数据库是一个不错的选择.这一章我们来看如何操作 IoT