在Windows CE中,通常我們會將網路卡設定一個固定IP,用來與其他的設備做溝通、通訊,那麼設定了IP之後,跟著就會有IP變更的需求了,那麼怎麼去變更IP呢?
從登錄檔中,可以看到IP的相關設定會在這個位置當中
HKEY_LOCAL_MACHINE\Comm\PCI\網卡名稱\Parms\TCPIP
其中會看到Ipaddress、defaultGetway、SubnetMask這三個就是對應到IP的設定了,要變更的地方也就是這三個了,而在compact framework 2.0對登錄檔的操作也有提供了類別可以使用,可以參考MSDN上的相關類別使用說明,下面這邊是利用p/Invoke的方式來做
p/Inove的宣告
<DllImport("CoreDll.dll", EntryPoint:="RegDeleteKeyW")> _ Public Function RegDeleteKey(ByVal hKey As Integer, ByVal lpSubKey As String) As Integer End Function <DllImport("CoreDll.dll", EntryPoint:="RegCreateKeyExW")> _ Public Function RegCreateKeyEx(ByVal hkey As Integer, ByVal lpSubKey As String, _ ByVal Reserved As Integer, ByVal lpClass As String, _ ByVal dwOptions As Integer, ByVal samDesired As Integer, _ ByVal lpSecurityAttributes As Integer, ByRef phkResult As Integer, _ ByRef lpdwDisposition As Integer) As Integer End Function <DllImport("CoreDll.dll")> _ Public Function RegSetValueEx(ByVal hKey As Integer, ByVal lpValueName As String, _ ByVal Reserved As Integer, ByVal dwType As Integer, ByVal lpData As String, ByVal cbData As Integer) As Integer End Function <DllImport("CoreDll.dll")> _ Public Function RegCloseKey(ByVal hKey As Integer) As Integer End Function <DllImport("CoreDll.dll", EntryPoint:="RegOpenKeyExW")> _ Public Function RegOpenKeyEx(ByVal hKey As Integer, ByVal lpSubKey As String, ByVal dwOptions As Integer, _ ByVal samDesired As Integer, ByRef phkResult As Integer) As Integer End Function <DllImport("CoreDll.dll")> _ Public Function RegFlushKey(ByVal hKey As Integer) As Integer End Function
呼叫的時候大概會是這個樣子
Dim buf, ohKey, iTmp As Integer Dim bolResult As Boolean = False ''R86101是我的網路卡名稱 buf = RegCreateKeyEx(RegRoots.HKEY_LOCAL_MACHINE, "Comm\PCI\R86101\Parms\TCPIP", 0, vbNullString, 0, 0, 0, ohKey, iTmp) buf = RegSetValueEx(ohKey, "Ipaddress", 0, RegValueType.REG_MULTI_SZ, IpAddress, 30) buf = RegFlushKey(ohKey) buf = RegCloseKey(ohKey) buf = RegCreateKeyEx(RegRoots.HKEY_LOCAL_MACHINE, "Comm\PCI\R86101\Parms\TCPIP", 0, vbNullString, 0, 0, 0, ohKey, iTmp) buf = RegSetValueEx(ohKey, "DefaultGateway", 0, RegValueType.REG_MULTI_SZ, Getway, 30) buf = RegFlushKey(ohKey) buf = RegCloseKey(ohKey) buf = RegCreateKeyEx(RegRoots.HKEY_LOCAL_MACHINE, "Comm\PCI\R86101\Parms\TCPIP", 0, vbNullString, 0, 0, 0, ohKey, iTmp) buf = RegSetValueEx(ohKey, "SubnetMask", 0, RegValueType.REG_MULTI_SZ, SubMask, 30) buf = RegFlushKey(ohKey) buf = RegCloseKey(ohKey)
這樣子就完成了IP設定的修改了,進入網卡設定的介面中,也可看到IP有變為新的設定了;這個時候問題來了,怎麼系統沒有套用新的設定呢?
在初期還沒有找到解決方式的時候,是讓系統重新開機,重新開機之後就會使用新的IP設定了,但是重新開機會花上不少的時間,而且明明在CE的介面上,變更好IP之後按下『OK』的按鈕明明就是會立刻更新IP位置的,找了相關資料後,原來是還要對系統發出一個更新通知,這樣系統才會進行IP位置的更新,這時候又得使用p/Invoke來處理了,最終的目的是要利用DeviceIoControl來對系統發出Rebind adepater的通知
const的宣告
Public Const OPEN_EXISTING As UInt32 = 3 Public Const INVALID_HANDLE_VALUE As Int32 = -1 Public Const IOCTL_NDIS_REBIND_ADAPTER As UInt32 = &H17002E Public Const FILE_ATTRIBUTE_NORMAL As UInt32 = &H80
API的部分
<DllImport("coredll.dll", EntryPoint:="CreateFileW")> _ Public Function CreateFile(ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, _ ByVal dwShareMode As Integer, ByVal lpSecurityAttributes As Integer, _ ByVal dwCreationDisposition As Integer, ByVal dwFlagsAndAttributes As Integer, _ ByVal hTemplateFile As Integer) As Integer End Function <DllImport("CoreDll.dll", setlasterror:=True)> _ Public Function DeviceIoControl(ByVal m_handle As Integer, ByVal dwIoControlCode As Integer, _ ByVal npInBuffer As String, ByVal nInBufferSize As Integer, _ ByVal lpOutBuffer As String, ByVal nOutBufferSize As Integer, _ ByVal lpBytesReturned As Integer, ByVal lpOverlapped As Integer) As Boolean End Function <DllImport("CoreDll.dll")> _ Public Function GetLastError() As Integer End Function <DllImport("coredll.dll")> _ Public Function CloseHandle(ByVal m_handle As IntPtr) As Integer End Function
使用的時候會像是下面這樣
Dim _NDISAdapterName As String = mMyInfo.NDISAdapterName Dim m_handle As Integer m_handle = CreateFile("NDS0:", 0, 0, Nothing, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, INVALID_HANDLE_VALUE) If Not DeviceIoControl(m_handle, IOCTL_NDIS_REBIND_ADAPTER, _NDISAdapterName, _ _NDISAdapterName.Length * 2 + 2, Nothing, 0, 0, 0) Then ''intResult = GetLastError() bolResult = False Else bolResult = True End If CloseHandle(m_handle)
這樣就可以馬上套用新的IP設定了,這邊做個備忘也給各位參考了。
Note:程式碼中錯誤處理的部分沒有做很仔細的錯誤處理,還請自行加上嚕