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

来源:互联网 发布:长沙学历网络教育培训 编辑:程序博客网 时间:2024/05/17 05:53

转载地址: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. }
复制代码
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 丙烯颜料画错了怎么办 油画的油干了怎么办 数字油画没画完颜料干了怎么办? 涂完口红很干怎么办 吃鸡匹配不到人怎么办 电脑吃鸡更新慢怎么办 苹果手机吃鸡更新不了怎么办 吃鸡更新硬盘不够怎么办 吃鸡链接不到更新服务器怎么办 6s吃鸡更新不了怎么办 凌美钢笔刮纸怎么办 毕加索钢笔不出水怎么办妙招 打印机总显示墨水已用完怎么办 樱花勾线笔干了怎么办 枣核卡在喉咙里怎么办 马桶被玉米棒堵了怎么办 雪糕棒掉马桶里了怎么办 食用色素吃多了怎么办 蜡笔弄到指甲里怎么办 小孩把彩笔吃了怎么办 宝宝吃了水彩笔怎么办 宝宝不小心吃了蜡笔怎么办 小孩把蜡笔吃了怎么办 宝宝吃了记号笔怎么办 二年级的孩子不太爱看书怎么办 数字油画涂错了怎么办 白墙上被蜡笔画起来怎么办 衣服上的油画棒怎么办 蜡笔要是涂错了怎么办 蜡笔颜色涂错了怎么办 书被蜡笔涂了怎么办 白灰墙上被蜡笔涂了怎么办 电器上涂了彩色蜡笔怎么办 3d渲大图慢怎么办 23岁就眼皮下垂怎么办 手被猫咪抓破了怎么办 有幻想症的人怎么办 做事不专心老走神怎么办 小朋友做作业老发呆走神怎么办? 小朋友总是上课走神发呆怎么办 21岁精神心急了怎么办