适用范围: Microsoft® .NET Compact Framework 基于 Windows Mobile™ 的 Pocket PC 基于 Windows Mobile 的智能电话 Microsoft ActiveSync®
摘要: 了解使用远程 API 或 RAPI 存储数据的方法,以及如何将数据合并到通过 .NET Compact Framework 开发的应用程序中。
引言 远程 API 库 通过 Communication 命名空间提供的类 使用 OpenNETCF 的 Communication 库 RAPI 类 使用 RAPI 类 连接到设备 使用文件 启动应用程序 检索系统信息 .NET Compact Framework 开发速成 上路
在上篇文章中,我曾提出移动计算所涉及的位置。其中的重点是说明数据存储方法,特别是 Pocket Access 数据库,以及如何将这些数据库合并到通过 .NET Compact Framework 开发的应用程序中。
本文继续讨论数据存储方法,但角度有所不同。具体而言,即移动计算桌面端。这一方面常被新的移动解决方案开发者所忽视。很多开发者在应用程序的移动问题上孜孜不倦,结果却忽略了桌面或服务器应用程序可成为移动解决方案中的一部分。显然,大多数移动解决方案都以设备为基础,而几乎所有的方案最后都要从设置中传入或传出数据。这些数据包括由设备收集的数据、服务器提供的供参考的数据、配置数据、甚至还有应用程序的更新数据。本文说明如何通过一个简单的桌面应用程序充分利用远程 API 执行以下操作:
通过设备复制粘贴文件。
移动设备中的文件。
删除设备中的文件。
启动设备中的应用程序。
检索设备中的系统信息。
本文自始至终提到的示例都以 Microsoft Visual C#® .NET 和 Visual Basic® .NET 两种代码形式显示,它们是“路的两边”专栏的一部分。
本月的应用程序示例演示了远程 API 或 RAPI 的功能。这个 API 是 ActiveSync 的一个关键组件。RAPI 库由一组函数组成,这些函数可用于通过桌面应用程序管理设备,包括设备的目录文件、设备的注册表和系统信息。
为了简化远程 API 的使用过程,将使用 OpenNETCF 组织的 Communication 库(这是一种开放源代码的资源),您可访问以下地址获取:OpenNETCF website (英文)。该库将 RAPI 处理过程中所有令人头痛的问题一一去除,同时提供了一组方法来展现 RAPI 必须提供的全部功能。
OpenNETCF.Desktop.Communication 命名空间提供以下类,如表 1 所示。
类
说明
ActiveSync
提供对 Microsoft ActiveSync 底层功能的访问。
AutoStartApps
提供配置 ActiveSync 会话开始时运行的应用程序的功能及相关信息。
FileInformation
描述 FindFirstFile 和 FindNextFile 方法返回的文件信息结构。
FileList
FileInformation 类的集合。桌面应用程序经常用它查询和管理连接设备的文件结构。
RAPI
提供对基础 RAPI 函数的简便包装。
RAPIException
定义 RAPI 类发生的例外。
Registry
提供对基础 RegistryKey 类的访问,这些类反过来又用来访问并修改连接设备的注册表值和注册表子项。
RegistryKey
定义连接设备注册表中的一个项节点。
如上表所示,OpenNETCF.Desktop.Communication 命名空间提供了大量的桌面功能,这些无法在一篇文章中详细说明。本文的重点是 RAPI 类,特别是 RAPI 类的 3 个主要功能:
管理设备中的目录文件。
启动设备中的应用程序。
检索设备中的系统信息。
之所以选择这 3 项,是因为这 3 部分在开发移动解决方案中起着特别的帮助作用。
OpenNETCF Communication 库是通过 OpenNETCF.Desktop.Communication.DLL 文件提供的。您需要在桌面应用程序中包括这个库的引用。要添加引用,请执行以下步骤:
在“解决方案资源管理器”中,右键单击“References”文件夹。显示弹出菜单。
在菜单中,选择“添加引用”。
显示“添加引用”对话框。选择“OpenNETCF.Desktop.Communication”组件。
单击“确定”按钮,将所选组件添加到您的项目中。
表 2 列出的 RAPI 类方法对开发移动应用程序最有帮助。
方法
说明
Connect
建立与设备的同步连接。
CopyFileFromDevice
将设备中的文件复制到 PC。
CopyFileOnDevice
将设备某个位置的文件复制到设备的另一新位置。
CopyFileToDevice
将 PC 中的文件复制到设备。
CreateDeviceDirectory
在设备中创建目录。
CreateProcess
启动设备中的应用程序。
DeleteDeviceFile
删除设备中的文件。
DeviceFileExists
检查设备中是否存在文件。
Disconnect
中断与设备的连接。
EnumFiles
提供与 FileName 参数提供的条件相匹配的 FileInformation 类数组列表。
GetDeviceCapabilities
检索设备的特定设备信息。
GetDeviceFileAttributes
检索特定设备文件的属性。
GetDeviceFileSize
检索设备文件的大小,以字节为单位。
GetDeviceFileTime
检索设备文件的日期时间。
GetDeviceMemoryStatus
检索设备的内存使用信息。
GetDeviceSystemFolderPath
检索到设备系统文件夹的路径。
GetDeviceSystemInfo
检索设备的系统详细信息。
GetDeviceSystemPowerStatus
检索设备的电源状态。
GetDeviceVersion
检索设备的操作系统版本。
MoveDeviceFile
将现有设备文件移到或重命名到一个新位置。
RemoveDeviceDirectory
删除设备中的目录。
SetDeviceFileAttributes
设置设备中文件的属性。
SetDeviceFileTime
设置设备中文件的日期时间。
为了简化 RAPI 类的使用过程,C# 代码示例中添加了 using 语句,VB.NET 代码示例中添加了 Imports 语句,如下所示:
[VC#.NET] using OpenNETCF.Desktop.Communication; [VB.NET] Imports OpenNETCF.Desktop.Communication
此外,还声明了一个模块变量 myrapi,该变量用于存储 RAPI 类的实例。
[VC#.NET] // 声明 RAPI 对象的实例。 RAPI myrapi; [VB.NET] ' 声明 RAPI 对象的实例。 Dim WithEvents myrapi As New rapi
桌面应用程序在使用 RAPI 类方法时,第一步是建立与设备的连接。
注意:在桌面应用程序中使用 RAPI 要求在 PC 和设备之间激活 ActiveSync 连接。
本文包含的应用程序示例在 Form_Load 事件中建立与设备的连接。要连接到设备,请使用 RAPI 类的 Connect 方法。如以下代码所示,紧接着检查 RAPI 类的 DevicePresent 属性,以验证连接是否成功。
[VC#.NET] try // 连接到设备。 { myrapi.Connect(); while (! myrapi.DevicePresent) { MessageBox.Show("Please connect your device to your PC using ActiveSync and before clicking the OK button.", "No Device Present"); myrapi.Connect(); } } catch (Exception ex) { MessageBox.Show("The following error occurred while attempting to connect to"+ " your device - " + ex.Message, "Connection Error"); Application.Exit(); } [VB.NET] Try ' 连接到设备。 myrapi.Connect() Do While Not myrapi.DevicePresent MessageBox.Show("Please connect your device to your PC using ActiveSync and " & _ "before clicking the OK button.", "No Device Present") myrapi.Connect() Loop Catch ex As Exception MessageBox.Show("The following error occurred while attempting to connect to" & _ " your device -" & ex.Message, "Connection Error") Application.Exit() End Try
建立连接后,准备使用 RAPI 提供的功能。首先,了解如何通过桌面应用程序管理设备的目录文件。
RAPI 提供了相当多处理文件目录的功能。这里演示 3 种与文件有关的功能:将文件复制到设备或从设备复制文件、移动设备中的文件、删除设备中的文件。首先是复制文件。
将数据移入或移出设备的一种最简单方法是,在 PC 和设备之间复制文本或 XML 文件。图 1 显示了使用 RAPI 演示程序的方法。在移动应用程序中,文本和基于 XML 的文件可作为一种简易方式存储应用程序数据或配置数据。
OpenNETCF.Desktop.Communication 命名空间的 RAPI 类提供了两种方法复制文件:CopyFileToDevice 和 CopyFileFromDevice。这两种方法都将源文件视作第一个变量,将目标文件视作第二个变量。
btnCopyPerform 按钮的单击事件过程实现了这两种方法。究竟是调用 CopyFileToDevice 方法还是调用 CopyFileFromDevice 方法,取决于用户在用户界面组合框中选择的指令。
[VC#.NET] private void btnCopyPerform_Click(object sender, System.EventArgs e) { // 执行复制。 try { if ((txtCopySource.Text == "") || (txtCopyDestination.Text == "")) { MessageBox.Show("You must provide both a source and destination file.", "Missing File Information"); } else { switch (cmbCopyDirection.Text) { case "": MessageBox.Show("You must select a direction before initiating the copy.", "No Destination Selected"); break; case "from desktop to device": myrapi.CopyFileToDevice(txtCopySource.Text, txtCopyDestination.Text); MessageBox.Show("Your file has been copied.", "Copy Success"); break; case "from device to desktop": myrapi.CopyFileFromDevice(txtCopySource.Text, txtCopyDestination.Text); MessageBox.Show("Your file has been copied.", "Copy Success"); break; } } } // 处理可能发生的所有错误。 catch (Exception ex) { MessageBox.Show("The following error occurred copying the file -" + ex.Message, "Copy Error"); } } [VB.NET] Private Sub btnCopyPerform_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCopyPerform.Click ' 执行复制。 Try If (txtCopySource.Text = "") Or (txtCopyDestination.Text = "") Then MessageBox.Show("You must provide both a source and destination file.", _ "Missing File Information") Exit Sub End If Select Case cmbCopyDirection.Text Case "" MessageBox.Show("You must select a direction before initiating the copy.", _ "No Destination Selected") Exit Sub Case "from desktop to device" myrapi.CopyFileToDevice(txtCopySource.Text, txtCopyDestination.Text) Case "from device to desktop" myrapi.CopyFileFromDevice(txtCopySource.Text, txtCopyDestination.Text) End Select MessageBox.Show("Your file has been copied.", "Copy Success") ' 处理可能发生的所有错误。 Catch ex As Exception MessageBox.Show("The following error occurred copying the file -" & ex.Message, _ "Copy Error") End Try End Sub
有时,您可能需要移动或重命名设备中的文件。例如,在将新版本文件复制到设备之前,可能要备份配置文件,图 2 显示了使用 RAPI 演示程序的方法。
OpenNETCF.Desktop.Communication 命名空间的 RAPI 类提供了 MoveDeviceFile方法来移动或重命名文件。和 CopyFile 方法一样,该方法也将源文件视作第一个变量,将目标文件视作第二个变量。
btnMovePerform 按钮的单击事件过程实现了 MoveDeviceFile 方法。
[VC#.NET] private void btnMovePerform_Click(object sender, System.EventArgs e) { // 执行移动。 try { if ((txtMoveSource.Text == "") || (txtMoveDestination.Text == "")) { MessageBox.Show("You must provide both a source and destination file.", "Missing File Information"); } else { myrapi.MoveDeviceFile(txtMoveSource.Text, txtMoveDestination.Text); MessageBox.Show("Your file has been copied.","Copy Success"); } } // 处理可能发生的所有错误。 catch (Exception ex) { MessageBox.Show("The following error occurred moving the file " + ex.Message,"Connection Error"); } } [VB.NET] Private Sub btnMovePerform_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMovePerform.Click ' 执行移动。 Try If (txtMoveSource.Text = "") Or (txtMoveDestination.Text = "") Then MessageBox.Show("You must provide both a source and destination file.", _ "Missing File Information") Exit Sub End If myrapi.MoveDeviceFile(txtMoveSource.Text, txtMoveDestination.Text) MessageBox.Show("Your file has been copied.", "Copy Success") ' 处理可能发生的所有错误。 Catch ex As Exception MessageBox.Show("The following error occurred moving the file -" & ex.Message, _ "Move Error") End Try End Sub
很多时候,您会发现 RAPI 复制文件方法要与删除文件方法一同使用。例如,您可能要求桌面应用程序对应用程序用于存储设备数据的文件进行复制,然后在成功完成复制任务后,返回并从设备中删除文件,以便移动应用程序再次收集新的数据。图 3 显示了使用 RAPI 演示程序的方法。
OpenNETCF.Desktop.Communication 命名空间的 RAPI 类提供了 DeleteDeviceFile 方法来删除设备文件。要删除的文件是该方法的第一个变量。
btnDeletePerform 按钮的单击事件过程实现了 DeleteDeviceFile 方法。
[VC#.NET] private void btnDeletePerform_Click(object sender, System.EventArgs e) { // 执行删除。 try { if (txtDeleteFile.Text == "") { MessageBox.Show("You must provide a file to delete.", "No File Provided"); } else { myrapi.DeleteDeviceFile(txtDeleteFile.Text); MessageBox.Show("Your file has been deleted.", "Delete Success"); } } // 处理可能发生的所有错误。 catch (Exception ex) { MessageBox.Show("The following error occurred while deleting the file -" + ex.Message, "Delete Error"); } } [VB.NET] Private Sub btnDeletePerform_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDeletePerform.Click ' 执行删除。 Try If (txtDeleteFile.Text = "") Then MessageBox.Show("You must provide a file to delete.", _ "No File Provided") Exit Sub End If myrapi.DeleteDeviceFile(txtDeleteFile.Text) MessageBox.Show("Your file has been deleted.", "Delete Success") ' 处理可能发生的所有错误。 Catch ex As Exception MessageBox.Show("The following error occurred while deleting the file -" & ex.Message, _ "Delete Error") End Try End Sub
我们已讨论完常用的 3 种与文件有关的方法,即复制、移动和删除方法。下面看看如何从桌面应用程序中启动设备中的应用程序。
有各种各样的原因促使您要从桌面应用程序中启动设备上的应用程序。使用该技术可以:
安装新版本应用程序。只需将 CAB 文件复制到设备,然后运行设备中的 CAB 安装程序来执行安装。如果要使应用程序更新的交付和安装过程自动化,使用该技术非常有用。
注意 : 另一种启动方法是利用 ActiveSync 中的内置功能,自动处理桌面端的安装过程。
安装新版本应用程序后,重新启动设备上的移动应用程序。
启动设备应用程序后,系统将处理保存到文本文件或 XML 文件中的新的更新数据。
图 4 显示了使用 RAPI 演示程序的方法。
OpenNETCF.Desktop.Communication 命名空间的 RAPI 类提供了 CreateProcess 方法来启动设备文件。要启动的设备应用程序是该方法的第一个变量。您可以将应用程序要处理的命令行作为方法的第二个变量。
btnLaunchPerform 按钮的单击事件过程实现了 CreateProcess 方法。
[VC#.NET] private void btnLaunchPerform_Click(object sender, System.EventArgs e) { // 执行启动。 try { if (txtLaunchFile.Text == "") { MessageBox.Show("You must provide a file to launch.", "No File Provided"); } else { myrapi.CreateProcess(txtLaunchFile.Text, txtLaunchCommand.Text); MessageBox.Show("Your file has been launched.", "Launch Success"); } } // 处理可能发生的所有错误。 catch (Exception ex) { MessageBox.Show("The following error occurred while launching the file -" + ex.Message, "Launch Error"); } } [VB.NET] Private Sub btnLaunchPerform_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLaunchPerform.Click ' 执行启动。 Try If (txtLaunchFile.Text = "") Then MessageBox.Show("You must provide a file to launch.", _ "No File Provided") Exit Sub End If myrapi.CreateProcess(txtLaunchFile.Text, txtLaunchCommand.Text) MessageBox.Show("Your file has been launched.", "Launch Success") ' 处理可能发生的所有错误。 Catch ex As Exception MessageBox.Show("The following error occurred while launching the file -" & ex.Message, _ "Launch Error") End Try End Sub
下面,讨论最后一个与 RAPI 有关的主题,即检索系统信息。正如您在以下部分看到的,RAPI 类提供了若干方法来检索连接设备的信息。
如果能检索连接设备的特定系统信息,桌面应用程序即可基于以下信息提供内容或更改功能:
连接设备所用的处理器(常在将 CAB 文件推至包含特定处理器文件的设备时响应)。
注意 : 如果将应用程序部署到旧版本 Pocket PC 设备中,该技术非常有用。因为 Windows Mobile 设备都基于 ARM 处理器。
连接设备中运行的操作系统版本(与处理器类型一样,常用于提供相应的文件更新)。
连接设备的电源状态(用于警告用户在使用前检查设备电源是否过低)。
连接设备的内存状态(用于确定数据是否被卸载,如果用户加载了未授权的应用程序或其他与内存有关的函数,可用它确定是否有足够的空间来安装更新应用程序)。
图 5 显示了使用 RAPI 演示程序的方法。
RAPI 类提供的 4 种检索信息方法是:GetDeviceSystemInfo(处理器类型)、GetDeviceVersion(操作系统版本)、GetDeviceSystemPowerStatus(电源状态)和GetDeviceMemoryStatus(内存)。btnInfoRetrieve 按钮的单击事件过程实现了每一种方法。
[VC#.NET] private void btnInfoRetrieve_Click(object sender, System.EventArgs e) { string info; MEMORYSTATUS ms; SYSTEM_INFO si; SYSTEM_POWER_STATUS_EX sps; OSVERSIONINFO vi; // 检索系统信息。 myrapi.GetDeviceSystemInfo(out si); // 检索设备操作系统版本号。 myrapi.GetDeviceVersion(out vi); // 检索设备电源状态。 myrapi.GetDeviceSystemPowerStatus(out sps); // 检索设备内存状态。 myrapi.GetDeviceMemoryStatus(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: " + vi.dwMajorVersion + "." + vi.dwMinorVersion + "." + vi.dwBuildNumber + "/n"; if (sps.ACLineStatus == 1) { info += "On AC power:YES/n"; } else { info += "On AC power:NO /n"; } info += "Battery level: " + sps.BatteryLifePercent + "%/n"; info += "Total memory: " + String.Format("{0:###,###,###}", ms.dwTotalPhys) + "/n"; // 显示结果。 lblInfo.Text = info; } [VB.NET] Private Sub btnInfoRetrieve_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnInfoRetrieve.Click Dim info As String Dim ms As New MEMORYSTATUS Dim si As New SYSTEM_INFO Dim sps As New SYSTEM_POWER_STATUS_EX Dim vi As New OSVERSIONINFO ' 检索系统信息。 myrapi.GetDeviceSystemInfo(si) ' 检索设备操作系统版本号。 myrapi.GetDeviceVersion(vi) ' 检索设备电源状态。 myrapi.GetDeviceSystemPowerStatus(sps) ' 检索设备内存状态。 myrapi.GetDeviceMemoryStatus(ms) ' 设置检索信息的格式。 info = "The connected device has an " Select Case si.wProcessorArchitecture Case ProcessorArchitecture.Intel info += "Intel processor." & vbCrLf Case ProcessorArchitecture.MIPS info += "MIPS processor." & vbCrLf Case ProcessorArchitecture.ARM info += "ARM processor." & vbCrLf Case Else info = "unknown processor type." & vbCrLf End Select info += "OS version: " & vi.dwMajorVersion & "." & vi.dwMinorVersion & "." & vi.dwBuildNumber & vbCrLf info += "On AC power: " & IIf(sps.ACLineStatus = 1, "YES", "NO") & vbCrLf info += "Battery level: " & sps.BatteryLifePercent & "%" & vbCrLf info += "Total memory: " & String.Format("{0:###,###,###}", ms.dwTotalPhys) & vbCrLf ' 显示结果。 lblInfo.Text = info End Sub
以上是远程 API 的简单介绍,以及如何将桌面应用程序合并到移动解决方案中的说明。建议您花一些时间了解 OpenNETCF.Desktop.Communication 命名空间提供的其他大量功能。请记住,正是这些方法和 OpenNETCF 命名空间提供了各种各样增强手持应用程序性能的选择。
想在一周内快速了解 .NET Compact Framework 吗?参加这里的培训即可达到目的。现有一个五天的 NETCF 类培训,您从中能快速了解想知道的一切。培训课程将告诉您,如何使用 .NET Compact Framework、SQL Server CE 和 XML 创建有效的移动解决方案。请访问以下地址获取详细培训大纲: http://www.larryroof.com/(英文)。
如果不能参加面对面的课程教学,可从 Apress 购买新著:The Definitive Guide to the .NET Compact Framework(英文)。其中包括关于如何使用.NET Compact Framework 创建移动应用程序的全面概述。
这在以后再讲。春季培训就在眼前,我要带着我的滑水板、我的 Pocket PC 和要讲的题目到阳关明媚的佛罗里达去。在下一篇,我将给移动技术开发者讲解更多的方法。