我選擇的編程工具當然是Visual Basic NET2003,實話說Microsoft .NET Framework SDK 提供的功能實在不感恭維,微軟好象又要將所有走上光明大道的.NET程序員拖入API的黑暗時代,指針、句柄、地址操作,最令人惱火就是沒有為VB.Net程序做WinCE的API 聲明(令人懷念VB6的API浏覽器)很快我就在如何啟動手機中的應用程序的代碼上困住了,Net沒有為WinCE提供Process 對象這種不付責任的做法害得我好苦啊!
開始時聲明時老是將ShellExecuteEx 和CreateProcess這兩個熟悉得不能再熟悉的Win32在VB 6中的聲明直接粘到程序中,僅是將VB6的long改為NET的int32,結果老是報錯。在網上查了N天資料,才發現原來Win CE的核心API都是在一個coredll.dll文件中,使得我差點沒氣死!還有一點是SHELLEXECUTEINFO結構中的lpFile這種指向字符串常量的指針由於字符的編碼問題不能象在Win32編程中簡單聲明為String類型,所在必須聲明為Intptr,這樣問題就出現了,使用ShellExecuteEx函數必須使用微軟在VB.net中不直接提供的指針操作,所以我只好根據網上的資料改寫了一個VB.Net對內存指針的封裝類,詳細代碼及解釋如下(新建一個模塊,將以下代碼粘貼進去即可使用):
Imports System.Runtime.InteropServices '引及Net框架中對底層操作支持的命名空間
Public Class clsDAMSMobileMarshal '我寫的內存管理類
#Region "與內存有關的API聲明"
REM 以下是與內存有關的移動設備API
Public Declare Function LocalAlloc Lib "coredll.dll" Alias "LocalAlloc" (ByVal wFlags As Int32, _
ByVal wBytes As Int32) As IntPtr
Public Declare Function LocalFree Lib "coredll.dll" Alias "LocalFree" (ByVal hMem As Int32) As Int32
Public Declare Function LocalLock Lib "coredll.dll" Alias "LocalLock" (ByVal hMem As Int32) As Int32
Public Declare Function LocalReAlloc Lib "coredll.dll" Alias "LocalReAlloc" (ByVal hMem As IntPtr, _
ByVal wBytes As Int32, ByVal wFlags As Int32) As IntPtr
#End Region
#Region "API常量聲明"
Public Const LMEM_FIXED = 0
Public Const LMEM_MOVEABLE = &H2
Public Const LMEM_ZEROINIT = &H40
Public Const LPTR = LMEM_FIXED Or LMEM_ZEROINIT
#End Region
Public Shared Function fnAllocHLocal(ByVal ni_i32Size As Int32) As IntPtr
'申請本地內存,返回一個指向該內存塊的指針
Return LocalAlloc(LPTR, ni_i32Size)
End Function
Public Shared Function fnFreeHLocal(ByRef ni_pLocal As IntPtr) As Int32
REM 釋放指定的內存塊柄
Dim ti32FunctionReturnValue As Int32
If ni_pLocal.Equals(IntPtr.Zero) = False Then
ti32FunctionReturnValue = (LocalFree(ni_pLocal.ToInt32))
If ti32FunctionReturnValue = 0 Then
ni_pLocal = IntPtr.Zero
End If
End If
Return (ti32FunctionReturnValue)
End Function
Public Shared Function fnReAllocHLocal(ByVal ni_pIn As IntPtr, ByVal ni_i32Size As Int32) As IntPtr
'對指定的內存塊重新定義大小
Return LocalReAlloc(ni_pIn, ni_i32Size, LMEM_MOVEABLE)
End Function
Public Shared Function fnStringToHLocalUni(ByVal ni_strIn As String) As IntPtr
'將指定的字符串復制到一個內存塊中,並返回該內存塊的指針,這個指針必須使用fnFreeHLocal函數釋放
Dim ti32StringBufLength As Int32
Dim tpTempA As IntPtr
If Not (ni_strIn Is Nothing) Then
If ni_strIn.Length = 0 Then
Return IntPtr.Zero
Else
ti32StringBufLength = (ni_strIn.Length + 1) * 2 ' 包括最後一個中止字符
tpTempA = fnAllocHLocal(ti32StringBufLength)
If tpTempA.Equals(IntPtr.Zero) = False Then '申請內存成功
Marshal.Copy(ni_strIn.ToCharArray, 0, tpTempA, ni_strIn.Length)
Return tpTempA
End If
End If
End If
End Function
End Class
有了這個輔助函數,以下的API調用就簡單了,只需正確聲明即可,以下是ShellExecuteEx及CreateProcess涵數及其結構的正確聲明(同樣是將代碼粘貼到一個新建模塊中即可調用):
imports System.Runtime.InteropServices
REM API常數聲明-------------------------
Public Const SW_SHOWNORMAL = 1
Public Const gcNORMAL_PRIORITY_CLASS = &H20
Public Const gcINFINITE = &HFFFF
Public Const WAIT_TIMEOUT = &H102&
#Region "Structure SHELLEXECUTEINFO"
<StructLayout(LayoutKind.Sequential)> _
Structure SHELLEXECUTEINFO
Public cbSize As Int32
Public fMask As Int32
Public hwnd As IntPtr
Public lpVerb As IntPtr 'LPCTSTR,這種類型不能聲明為string,只可以老老實實聲明為Intptr
Public lpFile As IntPtr 'LPCTSTR,這種類型不能聲明為string,只可以老老實實聲明為Intptr
Public lpParameters As IntPtr 'LPCTSTR,這種類型不能聲明為string,只可以老老實實聲明為Intptr
Public lpDirectory As IntPtr 'LPCTSTR,這種類型不能聲明為string,只可以老老實實聲明為Intptr
Public nShow As Int32
Public hInstApp As IntPtr
'Optional members
Public lpIDList As IntPtr 'LPVOID
Public lpClass As IntPtr 'LPCTSTR
Public hkeyClass As Int32
Public dwHotKey As Int32
Public hIcon As Int32
Public hProcess As IntPtr
Public Sub Dispose()
'在調用後釋放結構中的內存塊
clsDAMSMobileMarshal.fnFreeHLocal(Me.lpVerb)
clsDAMSMobileMarshal.fnFreeHLocal(Me.lpFile)
clsDAMSMobileMarshal.fnFreeHLocal(Me.lpParameters)
clsDAMSMobileMarshal.fnFreeHLocal(Me.lpDirectory)
End Sub
End Structure
#End Region
#Region "Structure STARTUPINFO"
<StructLayout(LayoutKind.Sequential)> _
Public Structure STARTUPINFO
Public cb As Int32
Public lpReserved As IntPtr
Public lpDesktop As IntPtr
Public lpTitle As IntPtr
Public dwX As Int32
Public dwY As Int32
Public dwXSize As Int32
Public dwYSize As Int32
Public dwXCountChars As Int32
Public dwYCountChars As Int32
Public dwFillAttribute As Int32
Public dwFlags As Int32
Public wShowWindow As Int16
Public cbReserved2 As Int16
Public lpReserved2 As Int32
Public hStdInput As Int32
Public hStdOutput As Int32
Public hStdError As Int32
End Structure
#End Region
#Region "Structure PROCESS_INFORMATION"
<StructLayout(LayoutKind.Sequential)> _
Public Structure PROCESS_INFORMATION
Public hProcess As IntPtr
Public hThread As IntPtr
Public dwProcessId As Int32
Public dwThreadId As Int32
End Structure
#End Region
REM api函數聲明
#Region "Function CreateProcess"
public Overloads Declare Function CreateProcess Lib "coredll.dll" (ByVal imageName As String, _
ByVal cmdLine As String, _
ByVal lpProcessAttributes As IntPtr, _
ByVal lpThreadAttributes As IntPtr, _
ByVal boolInheritHandles As Int32, _
ByVal dwCreationFlags As Int32, _
ByVal lpEnvironment As IntPtr, _
ByVal lpszCurrentDir As IntPtr, _
ByRef si As STARTUPINFO, _
ByRef pi As PROCESS_INFORMATION _
) As Integer
#End Region
#Region "Function CloseHandle"
Public Declare Function CloseHandle Lib "CoreDll.dll" (ByVal Handle As IntPtr) As Int32
#End Region
#Region "Function WaitForSingleObjectEx"
Public Declare Function WaitForSingleObjectEx Lib "coredll.dll" (ByVal hHandle As IntPtr, _
ByVal dwMilliseconds As Int32, _
ByVal bAlertable As Int32 _
) As Int32
#End Region
#Region "Function ShellExecuteEx"
Public Declare Function ShellExecuteEx Lib "coredll.dll" (ByRef lpExecInfo As SHELLEXECUTEINFO) As Int32
#End Region
下面是一個簡單示例,啟動手機中的計算器程序,步驟如下:
1、啟動VS.Net2003,選Visual Basic 項目,在右邊的列表中選智能設備應用程序,在下一個對話框中針對什麼平台選Smartphone,類型選Windows應用程序。
2、將上面介紹的輔助類及AP