南行取經記(一)重啟Windows Mobile裝置

aawolf發表於2008-02-07

臨近春節去新加坡參加了Mobility Metro Training,很多來自亞洲各地的MVPMCT們也都參加了這次的培訓。這次培訓的目的就是將Windows Mobile 6.0Visual Studio 2008開發的最新技術,快速地推廣到全世界。我們也將會在中國進行系列的Mobility Metro Training

這次去新加坡培訓的一共四人,臨行時的一句玩笑:“二師兄,你的肉現在比師傅的肉還貴”,讓這次培訓有了個“取經”的別稱。如果想了解Mobility Metro Training的全貌,還要等到培訓計劃公佈。

不過我也在這裡可以先將一些有趣的知識點寫成BLOG,權當年夜飯的下酒菜吧。

重啟Windows Mobile裝置

在論壇中,很多朋友都曾經問過如何在應用程式中重啟Windows Mobile裝置的問題。今天我們來看如何在Visual Studio 2008中來實現這個功能。

開啟Visual Studio 2008,選擇“File”選單,“New-Project”。我們會看到下面New Project對話方塊。

Project types裡,我們選擇Visual Basic中的Smart Device項。哎,經常看我BLOG裡的朋友也許會覺得奇怪,我什麼時候也開始用Visual Basic來寫程式了。稍後我們們再說。

我們只能選擇Smart Device Project,右上角的.NET Framework下拉選單對Windows Mobile程式來說沒什麼用。將專案名稱改為“Reset Pocket PC”,點OK

Smart Device的對話方塊裡,我們將Target platform選為“Windows Mobile 6 Professional SDK”,需要說明的是,Windows Mobile 6SDKVisual Studio 2008中並不是預設安裝,所以需要您單獨安裝。

然後選擇.NET CF的版本,我們選擇.NET CF 3.5。需要說明的是,.NET CF是沒有3.0的。這是為了和.NET Framework保持一致,所以.NET CF 2.0之後就是.NET CF 3.5

最後,我們選擇建立Device Application

在進入IDE編輯介面後,我們發現IDE環境並沒有發生太大的變化。我們直接在下面的選單中新增兩個選單項“Reset”和“Exit”。

雙擊“Exit”選單,進入程式碼編輯頁面。我們在MenuItem1_Click函式之外,點選滑鼠右鍵。在右鍵選單中,我們選擇“Insert Snippet”。Code SnippetVisual Studio中非常有用的一個功能,將一些有用的程式碼片段儲存為Code Snippet,在需要使用的時候就不需要到處翻以前的程式碼了。

而我們想使用的重啟Windows Mobile裝置的程式碼也是VB.NET中的程式碼片段,這也是我們為什麼選擇使用VB.NET的原因。

選擇Insert Snippet之後,會有一個列表,我們逐次選擇“Smart Devices-Device Operating System- Reset the Device”。

插入了Code Snippet之後,VB.NET程式碼如下。通過檢視程式碼,我們可以看到,是呼叫KernelIoControl API函式來實現功能的。KernelIoControl函式是用來實現對通用IO的控制,我們可以通過該函式實現很多的功能,比如獲取裝置資訊、檔案系統和電源管理。

 

VB.NET示例程式碼

    Private Declare Function KernelIoControl Lib "coredll.dll" (ByVal dwIoControlCode As Integer, ByVal lpInBuf As IntPtr, ByVal nInBufSize As Integer, ByVal lpOutBuf As IntPtr, ByVal nOutBufSize As Integer, ByRef lpBytesReturned As Integer) As Integer

 

    Private Function CTL_CODE(ByVal DeviceType As Integer, ByVal Func As Integer, ByVal Method As Integer, ByVal Access As Integer) As Integer

        Return (DeviceType << 16) Or (Access << 14) Or (Func << 2) Or Method

    End Function

 

    Private Function ResetPocketPC() As Integer

        Const FILE_DEVICE_HAL As Integer = &H101

        Const METHOD_BUFFERED As Integer = 0

        Const FILE_ANY_ACCESS As Integer = 0

 

        Dim bytesReturned As Integer = 0

        Dim IOCTL_HAL_REBOOT As Integer

 

        IOCTL_HAL_REBOOT = CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)

        Return KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, IntPtr.Zero, 0, bytesReturned)

 

    End Function

 

在函式建立完成後,我們在選單的呼叫方法中呼叫ResetPocketPC方法。

    Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click

        ResetPocketPC()

    End Sub

編譯執行之後,程式執行效果如上圖。當我們點選Reset選單,Windows Mobile裝置將會重啟。如果Visual Studio使用的是除錯模式,此時除錯將終止。

稍後,我們可以看到Windows Mobile裝置重啟的介面。VB.NET的程式碼可以正常實現,接下來,C#程式設計師會問,C#Code Snippet是否也提供相同的功能。遺憾的是,C#中,並沒有支援重啟的程式碼片段。我們需要自己實現C#中的程式碼,好在將這段程式碼從VB.NET“翻譯”成C#並不複雜。C#程式碼示例如下:

        [DllImport("coredll.dll")]

        public static extern int KernelIoControl(int dwIoControlCode, IntPtr lpInBuf, int nInBufSize, IntPtr lpOutBuf, int nOutBufSize,ref int lpBytesReturned);

 

        private int CTL_CODE(int DeviceType, int Func, int Method, int Access)

        {

           return (DeviceType << 16) | (Access << 14) | (Func << 2) | Method;

        }

 

        private int ResetPocketPC()

        {

            const int FILE_DEVICE_HAL = 0x101;

            const int METHOD_BUFFERED = 0;

            const int FILE_ANY_ACCESS = 0;

 

            int bytesReturned = 0;

            int IOCTL_HAL_REBOOT;

 

            IOCTL_HAL_REBOOT = CTL_CODE(FILE_DEVICE_HAL, 15, METHOD_BUFFERED, FILE_ANY_ACCESS);

            return KernelIoControl(IOCTL_HAL_REBOOT, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesReturned);

        }

 

C#程式碼執行也可以實現相同的功能。

 

最後以新加坡的風景照做結尾吧,祝大家新年快樂。

 

相關文章