如何使用PowerShell提升开发效率(以Windows Embedded CE为例)

简介

本文讲述如何使用Powershell通过RAPI来控制Windows Embedded CE和Windows Mobile设备。

 

缘由

我入行的时候是做AS400 RPG和UNIX C开发的,所有开发环境都是字符界面,因此习惯了vi+grep+make的开发模式。后来开始做Windows的开发,开始也不大习惯,安装了cygwin来使用,离不开命令行。其实合理使用命令行能大大简化日常工作,我记得好像有本书叫做高效程序员,里面提到要合理使用命令行来简化日常工作。我十分赞同这一说法,下面通过一个例子讲述如何简化工作。

AS400

AS/400的界面

 

UNIX

UNIX的界面

 

cygwin_shell  

Cygwin的界面

 

现在在从事Windows Embedded CE 6 R3的应用程序开发,由于某些原因,使用的设备没有备份电池。因此每次重新启动设备的时候,设备的时间会恢复到初始状态。每次启动系统后,我都需要手工修改设备的系统时间,至少需要20次的鼠标点击操作才能完成时间的设置。这是一件非常烦人的事情。作为程序员,应该尽量把大量的重复操作交给计算机来做,因此我考虑使用脚本来完成时间的设置。然后我考虑使用微软提供PowerShell来完成这一次任务。

 

为什么使用PowerShell

因为PowerShell可以和.NET Framework很好的结合在一起,可以整合现有的.NET的资源。开始我考虑使用CMD的批处理文件。我也曾经使用过批处理文件来简化编译过程,这个自动编译脚本还在使用,但是做过CMD批处理文件的人和做过UNIX Shell开发的人就会知道,CMD的批处理文件非常难使用,和任何一个shell比(SH, KSH, CSH, and BASH)都输一大截。因此我放弃了使用CMD的想法,选择了PowerShell。

 

安装和配置PowerShell

使用PowerShell需要下载和安装,请到 Download Windows PowerShell 1.0  下载并安装。需要.NET Framework 2.0的支持。

安装完毕后需要修改Execution Policy,这是对执行脚本的安全设置。因为PowerShell的默认Execution Policy是Restricted,Restricted表示只能执行单条命令,不能执行批量脚本。如果执行批量脚本会提示下面的错误。

File C:\Temp\projects\DatetimeSync\DatetimeSync.ps1 cannot be loaded because the execution of scripts is disabled on th
is system. Please see "get-help about_signing" for more details.
At line:1 char:18
+ ./DatetimeSync.ps1 <<<<


因此需要通过Set-ExecutionPolicy RemoteSigned命令来修改Execution Policy。修改后就能执行批量脚本了。

image

 

 

使用OpenNETCF Desktop Communication

由于PowerShell不支持直接操作Windows Embedded CE和Windows Mobile设备,因此需要借助RAPI来完成。如果使用.NET来开发RAPI,我们可以使用OpenNETCF Desktop Communication.关于OpenNETCF Desktop Communication和RAPI,我之前写过一篇文章,可以参考

Windows Embedded CE和Windows Mobile下ActiveSync开发.

先到OpenNETCF Desktop Communication Library下载,然后编译生成OpenNETCF.Desktop.Communication.dll。下面提供的源码已经包含了该DLL,所以这一步可以省略。

 

PowerShell开发

先新建一个文本文件,把文件扩展名改成ps1。例如我的文件叫做DatetimeSync.ps1 。然后就可以编写脚本了。

注意,Windows不会自动把ps1的文件与PowerShell进行绑定,每次执行ps1文件需要打开PowerShell,然后使用点号(.)执行,这与UNIX shell的风格一致。
例如下图所示:

image

只是输入DatetimeSync.ps1不能执行该文件,需要输入 ./DatetimeSync.ps1。

 

源码

$dllPath = Get-Location
$dllPath = $dllPath.Path + "\OpenNETCF.Desktop.Communication.dll"
[System.Reflection.Assembly]::LoadFrom($dllPath) |Out-null
$rapi = New-Object OpenNETCF.Desktop.Communication.RAPI
echo "Connecting to device..."
$rapi.Connect()
if ($rapi.Connected)
{
$dt = get-date
$date = $dt.Month.ToString() + "-" + $dt.Day.ToString() + "-" + $dt.Year.ToString()
echo "Setting date [$date]..."
$rapi.CreateProcess("cmd", "/c date " + $date)

$time = $dt.Hour.ToString() + ":" + $dt.Minute.ToString() + ":" + $dt.Second.ToString()
echo "Setting time [$time]..."
$rapi.CreateProcess("cmd", "/c time " + $time)

echo "Finished"
}
else
{
echo "Cannot connect to the device, please check the physical connection."
}

Get-Location和get-date叫做cmdlet(读作command-let),是代表一个单独功能的命令。例如Get-Location表示取出当前路径,get-date表示取出当前日期与时间。如果需要使用.NET的assembly,需要使用LoadFrom来反射加载。例子中把OpenNETCF.Desktop.Communication.dll加载进来。 New-Object表示实例化对象,在例子中实例化OpenNETCF.Desktop.Communication.RAPI的对象rapi。有了rapi对象就可以调用RAPI的类的方法来操控Windows Mobile 和 Windows Embedded CE的设备了。在例子中首先调用Connect()方法来连接设备,然后使用CreateProcess()函数来调用cmd修改时间和日期。本来可以通过调用API SetSystemTime来修改系统时间,但是如果这样做,需要使用C++开发一个设备上的DLL,然后部署到设备上,为了简化工作,我直接使用了cmd自带的time和date功能来完成时间的修改。

 

目前为止,这个功能已经实现了。使用PowerShell可以完成很多很多其他功能来简化我们的工作,例如管理设备上的进程,部署程序,启动单元测试等等。请问您在开发中有使用工具来简化工作吗?如果有,欢迎讨论。

 

如果您觉得文章不错,请点击支持,如果您觉得文章不好,请点击反对,可以的话,请留言指正,您的反馈是我进步的动力,谢谢。

参考

“How to” Series: Automating Windows Mobile with Windows PowerShell

 

源代码:  /Files/procoder/DatetimeSync.zip

posted @ 2010-07-15 07:48  Jake Lin  阅读(4718)  评论(16编辑  收藏  举报