在Windows CE中,如何修改IP設定之後立即套用新的設定呢?

在Windows CE中,通常我們會將網路卡設定一個固定IP,用來與其他的設備做溝通、通訊,那麼設定了IP之後,跟著就會有IP變更的需求了,那麼怎麼去變更IP呢?

在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:程式碼中錯誤處理的部分沒有做很仔細的錯誤處理,還請自行加上嚕