出处:http://www.cppblog.com/lizao2/archive/2012/10/11/193147.aspx

源代码运行效果图如下:

设置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.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为例:

二、将IP信息写入注册表

代码如下:

三、调用DhcpNotifyConfigChange通知配置的改变

未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下:

具体调用代码如下:

四.临时修改ip为自动获取,重启后恢复手动配置。把传入参数改成下面的即可。
if ((pDhcpNotifyProc)(NULL, wcAdapterName, FALSE, 0 , 0 , 0 , 1 )  ==  ERROR_SUCCESS)

说明,本方法在win7下无效,DhcpNotifyConfigChange返回50,ERROR_NOT_SUPPORTED,The request is not supported.

因此尝试网卡重启的方法:

出处:http://blog.csdn.net/bbdxf/article/details/7548443

Windows下程序修改IP的三种方法

以下讨论的平台依据是Window XP + SP1, 不考虑Windows其它版本的兼容性问题, 但对NT系列的系统, 理论上是通用的.

方法一: 网卡重启 
    更改Windows网卡属性选项中IP地址, 通过对比前后注册表, 可以发现以下几处发生变化 
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}] 
"IPAddress" 
"SubnetMask" 
"DefaultGateway" 
"NameServer"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip] 
"IPAddress" 
"SubnetMask" 
"DefaultGateway"

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}] 
"IPAddress" 
"SubnetMask" 
"DefaultGateway" 
"NameServer"

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip] 
"IPAddress" 
"SubnetMask" 
"DefaultGateway"

其中{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}是网卡名称(AdapterName), 不同的网卡, 不同的接入位置, 不同的接入的时间, 对应的值都不一样, 它的值是第一次接入系统时, 由系统生成的GUID值. 
    此处CurrentControlSet实际是ControlSet001的别名.     
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}] 
"IPAddress" 
"SubnetMask" 
"DefaultGateway" 
"NameServer" 
    是主要的设置处.

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip] 
"IPAddress" 
"SubnetMask" 
"DefaultGateway" 
    对一些服务有影响, 如不设置, 用netstat可以看到原来的IP地址仍处于监听状态(?).

但为了使设置生效, 还有很重要的一步, 即重启网卡.

更改网卡的配置, 一般而言需要重启网卡, 如 
    Linux系统, 只需运行 
        #ifconfig eth0 down 
        #ifconfig eht0 up 
    就可以实现网卡的重启.

Windows环境下的步骤与之类似: 先禁用本地连接(网卡), 再启用本地连接(网卡). 但没有相应的命令或者直接的API. 所幸的是DDK提供一套设备安装函数, 用于控制系统设备, 包括控制设备的状态改变.

/**************************************************************************************** 
 Purpose:    change state of the selected device 
 Input    :    hDevInfo    device info set     
            pDeviceInfoData        selected device info 
            NewState    one of enable/disable 
 Output    :    TRUE for success, FALSE for failed 
 ****************************************************************************************/ 
BOOL ChangeDeviceState(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDeviceInfoData, DWORD NewState) 

    SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)}; 
    SP_DEVINSTALL_PARAMS devParams;

if (!pDeviceInfoData) { 
        return FALSE; 
    }

PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); 
    PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE; 
    PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC; 
    PropChangeParams.StateChange = NewState;  
    PropChangeParams.HwProfile = 0;

if (!SetupDiSetClassInstallParams(hDevInfo,pDeviceInfoData, 
      (SP_CLASSINSTALL_HEADER *)&PropChangeParams,sizeof(PropChangeParams)) 
      || !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,hDevInfo,pDeviceInfoData))    { 
        return FALSE; 
    } 
    reutrn TRUE; 
}

/* hDevInfo如何得到***********************************************************/ 
    m_hDevInfo = SetupDiGetClassDevs( 
      (LPGUID) &GUID_DEVCLASS_NET,    /* GUID_DEVCLASS_NET表示仅列出网络设备 */ 
      NULL,  
      this->m_hWnd,  
      DIGCF_PRESENT); 
    if (INVALID_HANDLE_VALUE == m_hDevInfo) { 
        return FALSE; 
    }

/* pDeviceInfoData如何得到**************************************************/ 
    k = 0; 
    while (SetupDiEnumDeviceInfo(m_hDevInfo, k ,&DeviceInfoData))    { 
        k++; 
        if (CR_SUCCESS != CM_Get_DevNode_Status(&Status, &Problem,  
          DeviceInfoData.DevInst,0)) { 
            continue; 
        } 
        if ((Status & DN_NO_SHOW_IN_DM)) { 
            continue; 
        } 
        if (GetRegistryProperty(m_hDevInfo, 
          &DeviceInfoData, 
          SPDRP_FRIENDLYNAME, 
          &pBuffer, 
          &Length)) { 
            m_Adapter[adapter_num].index = k - 1;        /* 当前网卡在设备信息集中的索引 */ 
            _tcscpy(m_Adapter[adapter_num].desc, pBuffer);    /* 当前网卡 */ 
            GetRegistryProperty(m_hDevInfo, 
              &DeviceInfoData, 
              SPDRP_DRIVER, 
              &pBuffer, 
              &Length); 
            _tcscpy(m_Adapter[adapter_num].driver, pBuffer); 
            adapter_num++; 
        } 
    }

/* GetRegistryProperty是对SetupDiGetDeviceRegistryProperty封装***************/ 
BOOL GetRegistryProperty(HDEVINFO  DeviceInfoSet, 
                         PSP_DEVINFO_DATA  DeviceInfoData, 
                         ULONG Property, 
                         LPTSTR* Buffer, 
                         PULONG Length) 

    while (!SetupDiGetDeviceRegistryProperty( 
        DeviceInfoSet, 
        DeviceInfoData, 
        Property, 
        NULL, 
        (PBYTE)(*Buffer), 
        *Length, 
        Length 
        )) 
    { 
        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 
            if (*(LPTSTR *)Buffer)  
                LocalFree(*(LPTSTR *)Buffer); 
            *Buffer = (LPTSTR)LocalAlloc(LPTR, *Length); 
        }else { 
            return FALSE; 
        }             
    } 
    return TRUE; 
}

/* m_Adapter的数据结构 */ 
typedef struct adapter_info_s { 
    char name[NAME_LEN];        /* 内部设备名, UUID的字符串形式 */ 
    char desc[NAME_LEN];        /* 网卡描述 */ 
    char driver[NAME_LEN];        /* 网卡在注册表中的位置, 如{4D36E972-E325-11CE-BFC1-08002BE10318}\0011  
    实际完整的键名为System\\CurrentControlSet\\Control\\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0011  
    该键包含的内容与SetupDiGetDeviceRegistryProperty得到的设备属性基本相同 
    如NetCfgInstanceId即为内部设备名 DriverDesc为设备描述    */ 
    int index; 
}adapter_info_t;

/***************************************************************************** 
 用何名称区分不同的网卡 
 有如下名称可供选择 
    本地连接名, 这是系统使用的方法, 调用的是netman.dll中的未公开函数HrLanConnectionNameFromGuidOrPath(其原型笔者正在调试之中, 成功之后会另行撰文); 其实也可从注册表中获得HKLM\System\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Connection\Name 
    网卡类型描述 
    设备友好名        它与网卡类型描述基本相同, 当存在同种类型的网卡, 它会加#n(n = 2, 3, 4...)以示区分 
    如本程序中笔者即以设备友好名区分网卡 
 *****************************************************************************/

/* 重启网卡的过程************************************************************/ 
    k = pAdapter->GetCurSel();        /* m_Adapter[k]即当前网卡 */ 
    if (SetupDiEnumDeviceInfo(m_hDevInfo, m_Adapter[k].index ,&DeviceInfoData)) 
    { 
        hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));         
        ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_DISABLE);    /* 禁用网卡 */         
        ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_ENABLE);    /* 启用网卡 */         
        /* 重启网卡, 一般情况下, 以下命令相当于前两命令的组合. 但我仍建议使用前者 */     
        //    ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_PROPCHANGE); 
        SetCursor(hCursor);     
    }

/* 扫尾工作 */ 
    SetupDiDestroyDeviceInfoList(m_hDevInfo);

总结: 通过网卡重启更改IP的方法有两个步骤: 修改注册表, 重启网卡. 重启网卡的全过程上面已作描述.  注册表修改的内容为文中列出四个主要项, 如{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}的网卡名称即是内部设备名, 在adapter结构中已给出. 整个注册表修改的过程比较简单, 本文不加叙述.

方法二:未公开函数

Windows系统中, 更改Windows网卡属性选项中IP地址, 可以即时使更改生效, 并且没有重启网卡的过程. 系统自带的netsh也能通过命令行或脚本文件的形式, 完成更改IP的功能时, 也不需要重启网卡 
    同时也有很多共享软件, 可以实现同样的功能, 常见IP地址更改软件有IPFreeSet, IPChanger, IPProfile, IPHelp, IPSet, SNet等. 
     
    笔者通过分析netsh发现一个未公开函数, 即用netcfgx.dll封装的dhcpcsvc.dll中DhcpNotifyConfigChange函数 
    具体的方法参见VCKB 25期 王骏先生的 "不重起Windows直接更改IP地址", 他得到的函数原型比我准确, 思路也很清晰.

分析上述共享软件时, 发现其技术要点不外乎三种: 使用未公开函数, 调用netsh命令, 重启网卡硬件. 调用netsh命令的实质还是使用未公开函数

使用未公开函数的有: IPFreeSet, IPChanger 
调用netsh命令的有 : IPHelp, IPSet. 两者都是用Delphi开发的. 
重启网卡硬件: IPSwitcher

速度比较: 因为netsh本身的实现是调用netcfgx.dll, netcfgx.dll封装了对未公开函数的使用, 故效率相对较低. 在一台CPU:PIII500/RAM:256/XP的系统中, IPHelp需要6~7秒才能完成, 而IPFreeSet只需要1~2秒.

方法三:一卡多IP 
    除以上两个方法外, 笔者再介绍一种方法. 无论是在Windows下还是在Linux下, 一块网卡都可同时具有多个IP地址. 根据TCP/IP原理, 在网络层标识通信节点是IP地址, 在链路层上的则是MAC地址. 只要通过ARP, 将多个IP与一个MAC对应起来, 就可实现一网卡多IP(其实是一MAC多IP). 系统本身也有相应的设置选项, 如windows是通过TCP/IP属性的高级选项添加的, Linux下可由ifconfig命令添加. 
    iphlpapi提供AddIPAddress和DelIPAddress. 如果能先加入新的IP, 再去除原来的IP, 即可实现IP地址的更改. 
    具体内容参见我下篇文章"iphlpapi"的使用

出处:http://blog.csdn.net/delbboy/article/details/7446409

本文是通过禁用启用网卡让IP设置生效,因为使用DhcpNotifyConfigChange方法效果不好,且容易发生溢出问题

[cpp] view plain copy
  1. typedef int (CALLBACK* DHCPNOTIFYPROC)(LPWSTR, LPWSTR, BOOL, DWORD, DWORD, DWORD, int);
  2. typedef struct tagAdapterInfo
  3. {
  4. string strName;// 适配器名称
  5. string strDriverDesc;// 适配器描述
  6. string strIP; // IP地址
  7. string strNetMask;// 子网掩码
  8. string strNetGate;// 网关
  9. }ADAPTER_INFO;
  10. BOOL GetAdapterInfo();
  11. BOOL RegGetIP(ADAPTER_INFO *pAI, LPCTSTR lpszAdapterName, int nIndex = 0);
  12. vector<ADAPTER_INFO*> AdapterInfoVector;
  13. //-----------------------------------------------------------------
  14. // 取得所有网卡信息
  15. //-----------------------------------------------------------------
  16. BOOL GetAdapterInfo()
  17. {
  18. // 这里的代码适合WINDOWS2000,对于NT需要读取HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards
  19. HKEY hKey, hSubKey, hNdiIntKey;
  20. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  21. "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
  22. 0,
  23. KEY_READ,
  24. &hKey) != ERROR_SUCCESS)
  25. return FALSE;
  26. DWORD dwIndex = 0;
  27. DWORD dwBufSize = 256;
  28. DWORD dwDataType;
  29. char szSubKey[256];
  30. unsigned char szData[256];
  31. while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  32. {
  33. if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
  34. {
  35. if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
  36. {
  37. dwBufSize = 256;
  38. if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  39. {
  40. if(strcmp((char*)szData, "ethernet") == 0)//判断是不是以太网卡
  41. {
  42. dwBufSize = 256;
  43. if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  44. {
  45. ADAPTER_INFO *pAI = new ADAPTER_INFO;
  46. pAI->strDriverDesc = (LPCTSTR)szData;
  47. dwBufSize = 256;
  48. if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  49. {
  50. pAI->strName = (LPCTSTR)szData;
  51. RegGetIP(pAI, (LPCTSTR)szData);
  52. }
  53. AdapterInfoVector.push_back(pAI);// 加入到容器中
  54. }
  55. }
  56. }
  57. RegCloseKey(hNdiIntKey);
  58. }
  59. RegCloseKey(hSubKey);
  60. }
  61. dwBufSize = 256;
  62. } /* end of while */
  63. RegCloseKey(hKey);
  64. return TRUE;
  65. }
  66. //-----------------------------------------------------------------
  67. // 得到注册表中的IP信息
  68. // nIndex暂时未处理
  69. //-----------------------------------------------------------------
  70. BOOL RegGetIP(ADAPTER_INFO *pAI, LPCTSTR lpszAdapterName, int nIndex/* =0 */)
  71. {
  72. ASSERT(pAI);
  73. HKEY hKey;
  74. string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
  75. strKeyName += lpszAdapterName;
  76. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  77. strKeyName.c_str(),
  78. 0,
  79. KEY_READ,
  80. &hKey) != ERROR_SUCCESS)
  81. return FALSE;
  82. unsigned char szData[256];
  83. DWORD dwDataType, dwBufSize;
  84. dwBufSize = 256;
  85. if(RegQueryValueEx(hKey, "IPAddress", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  86. pAI->strIP = (LPCTSTR)szData;
  87. dwBufSize = 256;
  88. if(RegQueryValueEx(hKey, "SubnetMask", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  89. pAI->strNetMask = (LPCTSTR)szData;
  90. dwBufSize = 256;
  91. if(RegQueryValueEx(hKey, "DefaultGateway", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  92. pAI->strNetGate = (LPCTSTR)szData;
  93. RegCloseKey(hKey);
  94. return TRUE;
  95. }
  96. //-----------------------------------------------------------------
  97. // 设置注册表中的IP信息
  98. //-----------------------------------------------------------------
  99. BOOL RegSetIP(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate,LPCTSTR pDnsAddress)
  100. {
  101. HKEY hKey;
  102. string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
  103. strKeyName += lpszAdapterName;
  104. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  105. strKeyName.c_str(),
  106. 0,
  107. KEY_WRITE,
  108. &hKey) != ERROR_SUCCESS)
  109. return FALSE;
  110. char mszIPAddress[100];
  111. char mszNetMask[100];
  112. char mszNetGate[100];
  113. char szDnsAddr[100];
  114. strncpy(mszIPAddress, pIPAddress, 98);
  115. strncpy(mszNetMask, pNetMask, 98);
  116. strncpy(mszNetGate, pNetGate, 98);
  117. strncpy(szDnsAddr, pDnsAddress, 98);
  118. int nIP, nMask, nGate,nDnsAddr;
  119. int enableDHCP=0;
  120. nIP = strlen(mszIPAddress);
  121. nMask = strlen(mszNetMask);
  122. nGate = strlen(mszNetGate);
  123. nDnsAddr = strlen(szDnsAddr);
  124. *(mszIPAddress + nIP + 1) = 0x00;
  125. nIP += 2;
  126. *(mszNetMask + nMask + 1) = 0x00;
  127. nMask += 2;
  128. *(mszNetGate + nGate + 1) = 0x00;
  129. nGate += 2;
  130. *(szDnsAddr + nDnsAddr + 1) = 0x00;
  131. nDnsAddr += 2;
  132. RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
  133. RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
  134. RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
  135. RegSetValueEx(hKey, "NameServer", 0, REG_SZ, (unsigned char*)szDnsAddr, nDnsAddr);
  136. RegSetValueEx(hKey, "EnableDHCP", 0, REG_DWORD, (unsigned char*)&enableDHCP, sizeof(DWORD) );
  137. RegCloseKey(hKey);
  138. return TRUE;
  139. }
  140. //-----------------------------------------------------------------
  141. // 设置注册表中DHCP
  142. //-----------------------------------------------------------------
  143. BOOL RegSetDHCPIP(LPCTSTR lpszAdapterName, int nIndex)
  144. {
  145. HKEY hKey;
  146. string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
  147. strKeyName += lpszAdapterName;
  148. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  149. strKeyName.c_str(),
  150. 0,
  151. KEY_WRITE,
  152. &hKey) != ERROR_SUCCESS)
  153. return FALSE;
  154. int enableDHCP=1;
  155. char mszIPAddress[100];
  156. char mszNetMask[100];
  157. char mszNetGate[100];
  158. char szDnsAddr[100];
  159. strncpy(mszIPAddress, "0.0.0.0", 98);
  160. strncpy(mszNetMask, "0.0.0.0", 98);
  161. strncpy(mszNetGate, "", 98);
  162. strncpy(szDnsAddr, "", 98);
  163. int nIP, nMask, nGate,nDnsAddr;
  164. nIP = strlen(mszIPAddress);
  165. nMask = strlen(mszNetMask);
  166. nGate = strlen(mszNetGate);
  167. nDnsAddr=strlen(szDnsAddr);
  168. *(mszIPAddress + nIP + 1) = 0x00;
  169. nIP += 2;
  170. *(mszNetMask + nMask + 1) = 0x00;
  171. nMask += 2;
  172. *(mszNetGate + nGate + 1) = 0x00;
  173. nGate += 2;
  174. *(szDnsAddr + nDnsAddr + 1) = 0x00;
  175. nDnsAddr += 2;
  176. RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
  177. RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
  178. RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
  179. RegSetValueEx(hKey, "NameServer", 0, REG_SZ, (unsigned char*)szDnsAddr, nDnsAddr);
  180. int errCode = RegSetValueEx(hKey, "EnableDHCP", 0, REG_DWORD, (unsigned char*)&enableDHCP, sizeof(DWORD) );
  181. RegCloseKey(hKey);
  182. return TRUE;
  183. }
  184. //-----------------------------------------------------------------
  185. // 通知IP地址的改变
  186. //-----------------------------------------------------------------
  187. BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
  188. {
  189. BOOL bResult = FALSE;
  190. HINSTANCE hDhcpDll;
  191. DHCPNOTIFYPROCpDhcpNotifyProc;
  192. WCHAR wcAdapterName[256];
  193. MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
  194. if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)
  195. return FALSE;
  196. if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
  197. if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, NULL,NULL, 0) == ERROR_SUCCESS)
  198. bResult = TRUE;
  199. FreeLibrary(hDhcpDll);
  200. return bResult;
  201. }
  202. //-----------------------------------------------------------------
  203. //  设置IP地址
  204. //  如果只绑定一个IP,nIndex = 0,暂时未处理一个网卡绑定多个地址
  205. //-----------------------------------------------------------------
  206. BOOL SetIP(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate,LPCTSTR pDnsAddress)
  207. {
  208. if(!RegSetIP(lpszAdapterName, nIndex, pIPAddress, pNetMask, pNetGate,pDnsAddress))
  209. return FALSE;
  210. //通知IP地址的改变(此方法会造成栈溢出问题,而且对于设置dhcp的立即生效没有作用,故舍弃)
  211. //if(!NotifyIPChange(lpszAdapterName, nIndex, pIPAddress, pNetMask))
  212. //  return FALSE;
  213. //通过禁用启用网卡实现IP立即生效
  214. list<TNetCardStruct> cardList;
  215. EnumNetCards(&cardList);
  216. if(!cardList.empty())
  217. {
  218. NetCardStateChange(&cardList.front(),FALSE);
  219. Sleep(10);
  220. NetCardStateChange(&cardList.front(),TRUE);
  221. }
  222. return TRUE;
  223. }
  224. //-----------------------------------------------------------------
  225. //  设置DHCP IP地址
  226. //-----------------------------------------------------------------
  227. BOOL SetDHCPIP(LPCTSTR lpszAdapterName, int nIndex)
  228. {
  229. if(!RegSetDHCPIP(lpszAdapterName, nIndex))
  230. return FALSE;
  231. //通知IP地址的改变(此方法会造成栈溢出问题,而且对于设置dhcp的立即生效没有作用,故舍弃)
  232. //if(!NotifyDHCPIPChange(lpszAdapterName, nIndex))
  233. //  return FALSE;
  234. //通过禁用启用网卡实现IP立即生效
  235. list<TNetCardStruct> cardList;
  236. EnumNetCards(&cardList);
  237. if(!cardList.empty())
  238. {
  239. NetCardStateChange(&cardList.front(),FALSE);
  240. Sleep(10);
  241. NetCardStateChange(&cardList.front(),TRUE);
  242. }
  243. return TRUE;
  244. }

/*******************************************************网卡禁用启用操作*************************************************/

NetCard.h

[cpp] view plain copy
  1. #ifndef NETCARD_H_H
  2. #define NETCARD_H_H
  3. #include <Windows.h>
  4. #include <SetupAPI.h>
  5. #include <cfgmgr32.h>
  6. #include <list>
  7. using namespace std;
  8. //     cfgmgr32.h 在Microsoft Windows 2000 DDK 中.
  9. //     要用 CM_Get_DevNode_Status() 来查询状态.
  10. //---------------------------------------------------------------------------
  11. typedef struct  NetCardStruct
  12. {
  13. DWORD    Id;         // 网卡设备号
  14. string   Name;     // 网卡名
  15. bool     Disabled;     // 当前是否禁用
  16. bool     Changed;         // 是否更改过
  17. }TNetCardStruct;
  18. typedef TNetCardStruct*  PNetCardStruct;
  19. /*******************函数声明***********************************/
  20. static bool GetRegistryProperty(HDEVINFO DeviceInfoSet,
  21. PSP_DEVINFO_DATA DeviceInfoData,
  22. ULONG Property,
  23. PVOID Buffer,
  24. PULONG Length)   ;
  25. void    EnumNetCards(list<TNetCardStruct>  *NetDeviceList);
  26. bool   NetCardStateChange(PNetCardStruct NetCardPoint, bool Enabled)  ;
  27. /**************************************************************/
  28. #endif

NetCard.cpp

[cpp] view plain copy
  1. #include "stdafx.h"
  2. #include <SetupAPI.h>
  3. #include <cfgmgr32.h>
  4. #include <list>
  5. #include <Windows.h>
  6. #include <SetupAPI.h>
  7. #include "NetCard.h"
  8. //---------------------------------------------------------------------------
  9. //     EnumNetCards 枚举出网卡
  10. //---------------------------------------------------------------------------
  11. void  EnumNetCards(list<TNetCardStruct>  *NetDeviceList)
  12. {
  13. string DevValue;
  14. PNetCardStruct NetCard;
  15. DWORD  Status, Problem;
  16. LPTSTR Buffer   = NULL;
  17. DWORD  BufSize  = 0;
  18. HDEVINFO hDevInfo   = 0;
  19. hDevInfo=SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT|DIGCF_ALLCLASSES);
  20. if(INVALID_HANDLE_VALUE==hDevInfo)
  21. return;
  22. SP_DEVINFO_DATA  DeviceInfoData ={sizeof(SP_DEVINFO_DATA)};
  23. HKEY hKeyClass;
  24. char DeviceName[200];
  25. for(DWORD DeviceId=0;SetupDiEnumDeviceInfo(hDevInfo,DeviceId,&DeviceInfoData);DeviceId++)
  26. {
  27. if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData.DevInst,0) != CR_SUCCESS)
  28. continue;
  29. if(GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_CLASS , &Buffer, (PULONG)&BufSize))
  30. DevValue = string(Buffer);
  31. if (strcmp(DevValue.c_str(),"Net") == 0)
  32. {
  33. DevValue = "";
  34. if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_ENUMERATOR_NAME , &Buffer, (PULONG)&BufSize))
  35. DevValue = Buffer;
  36. if (strcmp(DevValue.c_str(),"ROOT") != 0)
  37. {
  38. NetCard = new TNetCardStruct;
  39. NetCard->Id = DeviceId;
  40. NetCard->Name = "<Unknown Device>";
  41. if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DRIVER , &Buffer, (PULONG)&BufSize))
  42. if (GetRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC , &Buffer, (PULONG)&BufSize))
  43. NetCard->Name = Buffer;
  44. NetCard->Disabled = (Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem);
  45. NetCard->Changed = false;
  46. NetDeviceList->push_back(*NetCard);
  47. }
  48. }
  49. }
  50. }
  51. //---------------------------------------------------------------------------
  52. bool   GetRegistryProperty(HDEVINFO DeviceInfoSet,
  53. PSP_DEVINFO_DATA DeviceInfoData,
  54. ULONG Property,
  55. PVOID Buffer,
  56. PULONG Length)
  57. {
  58. while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
  59. DeviceInfoData, Property, NULL, (BYTE *)*(TCHAR **)Buffer, *Length, Length))
  60. {
  61. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  62. {
  63. if (*(LPTSTR *)Buffer) LocalFree(*(LPTSTR *)Buffer);
  64. *(LPTSTR *)Buffer = (PCHAR)LocalAlloc(LPTR,*Length);
  65. }
  66. else return false;
  67. }
  68. return (*(LPTSTR *)Buffer)[0];
  69. }
  70. //---------------------------------------------------------------------------
  71. //     NetCardStateChange 网卡的启用与禁用
  72. //             NetCardPoint 是 PNetCardStruct 的指针.
  73. //             Enabled     true = 启用     false = 禁用
  74. //---------------------------------------------------------------------------
  75. bool   NetCardStateChange(PNetCardStruct NetCardPoint, bool Enabled)
  76. {
  77. PNetCardStruct NetCard = (PNetCardStruct)NetCardPoint;
  78. DWORD DeviceId = NetCard->Id;
  79. HDEVINFO hDevInfo = 0;
  80. if (INVALID_HANDLE_VALUE == (hDevInfo =
  81. SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT |DIGCF_ALLCLASSES)))
  82. return false;
  83. SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)};
  84. DWORD Status, Problem;
  85. if (!SetupDiEnumDeviceInfo(hDevInfo,DeviceId,&DeviceInfoData))
  86. return false;
  87. if (CM_Get_DevNode_Status(&Status, &Problem,
  88. DeviceInfoData.DevInst,0) != CR_SUCCESS)
  89. return false;
  90. SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)};
  91. PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  92. PropChangeParams.Scope = DICS_FLAG_GLOBAL;
  93. if (Enabled)
  94. {
  95. if (!((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem)))
  96. {
  97. NetCard->Disabled = false;
  98. return false;
  99. }
  100. PropChangeParams.StateChange = DICS_ENABLE;
  101. }
  102. else
  103. {
  104. if ((Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem))
  105. {
  106. NetCard->Disabled = true;
  107. return false;
  108. }
  109. if (!((Status & DN_DISABLEABLE) && (CM_PROB_HARDWARE_DISABLED != Problem)))
  110. return false;
  111. PropChangeParams.StateChange = DICS_DISABLE;
  112. }
  113. if (!SetupDiSetClassInstallParams(hDevInfo, &DeviceInfoData,
  114. (SP_CLASSINSTALL_HEADER *)&PropChangeParams, sizeof(PropChangeParams)))
  115. return false;
  116. if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &DeviceInfoData))
  117. return false;
  118. if (CM_Get_DevNode_Status(&Status, &Problem,
  119. DeviceInfoData.DevInst,0) == CR_SUCCESS)
  120. NetCard->Disabled = (Status & DN_HAS_PROBLEM) && (CM_PROB_DISABLED == Problem);
  121. return true;
  122. }

设置静态IP

[cpp] view plain copy
  1. GetAdapterInfo();
  2. char szIP[16]="111.111.111.11";
  3. char szMask[16]="255.255.255.10";
  4. char szGate[16]="111.111.111.1";
  5. char dnsAddress[16]="222.222.222.1";
  6. unsigned char *pIP, *pMask, *pGate;
  7. DWORD dwIP, dwMask, dwGate;
  8. if(SetIP(AdapterInfoVector[0]->strName.c_str(), 0, szIP, szMask, szGate,dnsAddress) == TRUE)
  9. ::MessageBox(this->m_hWnd, "设置IP地址成功!", "操作结果", MB_OK | MB_ICONINFORMATION);
  10. else
  11. ::MessageBox(this->m_hWnd, "设置IP地址失败!", "操作结果", MB_OK | MB_ICONERROR);

设置动态IP

[cpp] view plain copy
  1. GetAdapterInfo();
  2. if(SetDHCPIP(AdapterInfoVector[0]->strName.c_str(), 0 ) == TRUE)
  3. ::MessageBox(this->m_hWnd, "设置IP地址成功!", "操作结果", MB_OK | MB_ICONINFORMATION);
  4. else
  5. ::MessageBox(this->m_hWnd, "设置IP地址失败!", "操作结果", MB_OK | MB_ICONERROR);

C++不重起Windows直接更改IP地址相关推荐

  1. 如何在命令行下更改ip地址

    微软的Windows家族从Windows NT开始跨入了网络操作系统的市场,到现在的Windows 2003可以说网络功能在逐渐的完善,在这个成长过程中Windows融入了很多其他网络操作系统的功能, ...

  2. windows服务器指定IP地址才能进行远程访问桌面设置方法

    这篇文章主要介绍了windows服务器指定IP地址才能进行远程访问桌面设置方法,需要的朋友可以参考下 一般情况下分两种方法: 第一种是通过 防火墙来实现 等保测评要求:对服务器限制远程终端登录地址 于 ...

  3. 用Python更改IP地址(转)

    用Python更改IP地址(转) 大多数用笔记本电脑的朋友都有一个烦恼,那就是在家里和公司的IP地址不一样,上班和回家后都得来回切换IP地址,两个字"麻烦".最近在写Python, ...

  4. cmder上传文件到服务器,wget 结合everything上传文件到服务器端(以及更改ip地址)...

    上传服务器的方式有很多,平时常用的是ssh,scp等一些命令操作,但是当文件足够大的时候,用这些命令就显得力不从心了. 下面推荐一种操作系统是win10环境下上传批量文件到服务端的方法. 需要用到的软 ...

  5. 软件测试工作怎样修改本机IP,如何在命令行下更改IP地址

    如何在命令行下更改IP地址 发表于:2007-07-02来源:作者:点击数: 标签: 微软的Windows家族从Windows NT开始跨入了 网络 操作系统的市场,到现在的Windows 2000可 ...

  6. win10更改IP地址遇错(出现了一个意外情况,不能完成你的更改)

    最近买的新电脑是win10系统,因为之前一直用的win7特别顺手,导致现在用win10真的是各种不便. 今天想通过windows的图形界面修改本机的IP地址,但点击确定却莫名报错: 出现了一个意外情况 ...

  7. 如何更改IP地址使用代理ip软件

    如果您想更改家用计算机上的 IP 地址,有几种方法可能适合您--有些简单,有些则不然.在尝试下面描述的更复杂/技术方法之前,您可以尝试一些非常简单的方法. 只需关闭或拔下调制解调器约五分钟.(您不必关 ...

  8. 组策略妙用----通过组策略禁止域用户更改IP地址

    禁止更改IP地址 如果允许用户能够自己更改IP地址,就有可能和网络中其他计算机IP地址冲突.有些单位的网络管理员配置好计算机的IP地址后,不想让用户自己更改.以下示例将会演示禁止用户更改IP地址一种方 ...

  9. 修改sep客户端服务器地址,SEP服务更改IP地址操作手册

    <SEP服务更改IP地址操作手册>由会员分享,可在线阅读,更多相关<SEP服务更改IP地址操作手册(6页珍藏版)>请在人人文库网上搜索. 1.SEP服务器更换IP地址操作手册1 ...

最新文章

  1. 用c语言编写通讯录程序,学C三个月了,学了文件,用C语言写了个通讯录程序
  2. Centos6.0 64位MySQL 5.5.20 CMake 安装部署
  3. oracle数据库赋权_oracle数据库用户之间授权
  4. 响应时登录html,HtmlUnit:单击不响应时登录HtmlElement
  5. 777后无效 执行chmod_厉害了!南航777机队和南航空姐在人民大会堂接受表彰!
  6. HDU5900 QSC and Master(区间DP + 最小费用最大流)
  7. socket编程实现回声客户端
  8. 征战蓝桥 —— 2016年第七届 —— C/C++A组第3题——方格填数
  9. html h1转换为行内,css中转换为行内样式的解决方案(css-inline)
  10. centos中配置java视频教程_安装CentOs
  11. KDB支持单步调试功能(ARM架构)
  12. Linux中出现 -bash: unzip: command not found
  13. 推荐3款简约好用录屏工具
  14. 通过rsync备份静态文件
  15. PHP根据配置设置可变变量
  16. C语言例题-打印日历
  17. 最速下滑法c语言程序,最速下降法 C语言.doc
  18. 网站服务器带宽多少合适,服务器选择时带宽选多少合适?
  19. 【ACWing】487. 金明的预算方案
  20. php中相关乱码处理

热门文章

  1. char如何储存那么多汉字
  2. 基于专家知识的决策树分类|以DEM+影像数据在ENVI操作为例
  3. vue中父传子,父传孙说明
  4. python输入一个数字n、计算1到n的和_python用户输入一个整数N,计算并输出1到N相加的和,请问这个程序错在哪里了?...
  5. LaTeX数学公式的输入
  6. 使用计算机怎样制表格,如何在电脑上制作简单的表格?
  7. springboot启动错误--springboot At least one base package must be specified
  8. 通过API Key免登录访问Grafana
  9. 把Maven本地仓库修改为阿里云仓库
  10. Redis篇 <一>Docker安装redis 及基础