VC++不重起Windows直接更改IP地址

來源:互聯網
上載者:User

轉載地址:http://www.cctry.com/thread-3653-1-1.html

原始碼運行如下:

原始碼下載:

設定IP地址只需要更改註冊表中關於適配器的相應設定,但更改後需要重新啟動系統才會生效,而AddIPAddress函數只能添加IP而不是更改當前的IP,我們在Windows NT/2000介面上操作不需要重新啟動就可以生效,那系統到底做了什麼額外的工作才使IP設定直接生效呢?筆者通過跟蹤explorer.exe中API的調用發現在netcfgx.dll中調用了dhcpcsvc.dll中一個未公開的API:DhcpNotifyConfigChange,現將不重新啟動WINDOWS直接更改IP地址的詳細方法介紹如下:

一、擷取適配器名稱
這裡指的適配器名稱要區別於適配器描述,比如我的一塊網卡,適配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,適配器名稱為:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。擷取適配器名稱的方法有多種:

1.1 調用IP helper API取得適配器名稱

  1. ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
  2. IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
  3. if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 緩衝區不夠大
  4. {
  5.         delete pAdapterInfo;
  6.         pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
  7.         pAdapterInfoBkp = pAdapterInfo;
  8. }
  9. if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
  10. {
  11.         do{ // 遍曆所有適配器
  12.                 if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)        // 判斷是否為乙太網路介面
  13.                 {
  14.                         // pAdapterInfo->Description 是適配器描述
  15.                         // pAdapterInfo->AdapterName 是適配器名稱
  16.                 }
  17.                 pAdapterInfo = pAdapterInfo->Next;
  18.         }while(pAdapterInfo);
  19. }
  20. delete pAdapterInfoBkp;

複製代碼

1.2 讀取註冊表取得適配器名稱

在Windows2000中可以通過遍曆 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}\000n\ (n是從0開始編號的數字)所有介面, 在Windows NT中可以讀取HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards中的資訊,下面以Windows2000為例:

  1. HKEY hKey, hSubKey, hNdiIntKey;
  2. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3.                         "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
  4.                         0,
  5.                         KEY_READ,
  6.                         &hKey) != ERROR_SUCCESS)
  7.         return FALSE;
  8. DWORD dwIndex = 0;
  9. DWORD dwBufSize = 256;
  10. DWORD dwDataType;
  11. char szSubKey[256];
  12. unsigned char szData[256];
  13. while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  14. {
  15.         if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
  16.         {               
  17.                 if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
  18.                 {
  19.                         dwBufSize = 256;
  20.                         if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  21.                         {
  22.                                 if(strcmp((char*)szData, "ethernet") == 0)                //        判斷是不是乙太網路卡
  23.                                 {
  24.                                         dwBufSize = 256;
  25.                                         if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  26.                                         {
  27.                                                 // szData 中便是適配器詳細描述
  28.                                                 dwBufSize = 256;
  29.                                                 if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  30.                                                 {
  31.                                                         // szData 中便是適配器名稱
  32.                                                 }
  33.                                         }
  34.                                 }
  35.                         }
  36.                         RegCloseKey(hNdiIntKey);
  37.                 }
  38.                 RegCloseKey(hSubKey);
  39.         }
  40.         dwBufSize = 256;
  41. }        /* end of while */
  42.                
  43. RegCloseKey(hKey);

複製代碼

二、將IP資訊寫入註冊表

代碼如下:

  1. BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
  2. {
  3.         HKEY hKey;
  4.         string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
  5.         strKeyName += lpszAdapterName;
  6.         if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  7.                                 strKeyName.c_str(),
  8.                                 0,
  9.                                 KEY_WRITE,
  10.                                 &hKey) != ERROR_SUCCESS)
  11.                 return FALSE;
  12.        
  13.         char mszIPAddress[100];
  14.         char mszNetMask[100];
  15.         char mszNetGate[100];
  16.         strncpy(mszIPAddress, pIPAddress, 98);
  17.         strncpy(mszNetMask, pNetMask, 98);
  18.         strncpy(mszNetGate, pNetGate, 98);
  19.         int nIP, nMask, nGate;
  20.         nIP = strlen(mszIPAddress);
  21.         nMask = strlen(mszNetMask);
  22.         nGate = strlen(mszNetGate);
  23.         *(mszIPAddress + nIP + 1) = 0x00;        // REG_MULTI_SZ資料需要在後面再加個0
  24.         nIP += 2;
  25.         *(mszNetMask + nMask + 1) = 0x00;
  26.         nMask += 2;
  27.         *(mszNetGate + nGate + 1) = 0x00;
  28.         nGate += 2;
  29.        
  30.         RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
  31.         RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
  32.         RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
  33.         RegCloseKey(hKey);
  34.         return TRUE;
  35. }

複製代碼

三、調用DhcpNotifyConfigChange通知配置的改變

未公開函數DhcpNotifyConfigChange位於 dhcpcsvc.dll中,原型如下:

  1. BOOL DhcpNotifyConfigChange(
  2.     LPWSTR lpwszServerName, // 本地機器為NULL
  3.     LPWSTR lpwszAdapterName, // 適配器名稱
  4.     BOOL bNewIpAddress, // TRUE表示更改IP
  5.     DWORD dwIpIndex, // 指明第幾個IP地址,如果只有該介面只有一個IP地址則為0
  6.     DWORD dwIpAddress, // IP地址
  7.     DWORD dwSubNetMask, // 子網路遮罩
  8.     int nDhcpAction ); // 對DHCP的操作 0:不修改, 1:啟用 DHCP,2:禁用 DHCP

複製代碼

具體調用代碼如下:

  1. BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
  2. {
  3.         BOOL                        bResult = FALSE;
  4.         HINSTANCE                hDhcpDll;
  5.         DHCPNOTIFYPROC        pDhcpNotifyProc;
  6.         WCHAR wcAdapterName[256];
  7.        
  8.         MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
  9.         if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
  10.                 return FALSE;
  11.         if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
  12.                 if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
  13.                         bResult = TRUE;
  14.         FreeLibrary(hDhcpDll);
  15.         return bResult;
  16. }

複製代碼

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.