文章目錄
簡介
本文講述如何使用Powershell通過RAPI來控制Windows Embedded CE和Windows Mobile裝置。
緣由
我入行的時候是做AS400 RPG和UNIX C開發的,所有開發環境都是字元介面,因此習慣了vi+grep+make的開發模式。後來開始做Windows的開發,開始也不大習慣,安裝了cygwin來使用,離不開命令列。其實合理使用命令列能大大簡化日常工作,我記得好像有本書叫做高效程式員,裡面提到要合理使用命令列來簡化日常工作。我十分贊同這一說法,下面通過一個例子講述如何簡化工作。
AS/400的介面
UNIX的介面
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。修改後就能執行批量指令碼了。
使用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的風格一致。
例如所示:
只是輸入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