不重启Windows直接更改IP地址

不重起Windows直接更改IP地址  
  作者:浙江省温岭电信局   王骏  
   
  设置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取得适配器名称    
   
  ULONG   ulAdapterInfoSize   =   sizeof(IP_ADAPTER_INFO);  
  IP_ADAPTER_INFO   *pAdapterInfoBkp,   *pAdapterInfo   =   (IP_ADAPTER_INFO*)new   char[ulAdapterInfoSize];  
  if(   GetAdaptersInfo(pAdapterInfo,   &ulAdapterInfoSize)   ==   ERROR_BUFFER_OVERFLOW   )   //   缓冲区不够大  
  {  
  delete   pAdapterInfo;  
  pAdapterInfo   =   (IP_ADAPTER_INFO*)new   char[ulAdapterInfoSize];  
  pAdapterInfoBkp   =   pAdapterInfo;  
  }  
  if(   GetAdaptersInfo(pAdapterInfo,   &ulAdapterInfoSize)   ==   ERROR_SUCCESS   )  
  {  
  do{   //   遍历所有适配器  
  if(pAdapterInfo->Type   ==   MIB_IF_TYPE_ETHERNET) //   判断是否为以太网接口  
  {  
  //   pAdapterInfo->Description   是适配器描述  
  //   pAdapterInfo->AdapterName   是适配器名称  
  }  
  pAdapterInfo   =   pAdapterInfo->Next;  
  }while(pAdapterInfo);  
  }  
  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为例:   HKEY   hKey,   hSubKey,   hNdiIntKey;  
   
  if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,  
  "System//CurrentControlSet//Control//Class//{4d36e972-e325-11ce-bfc1-08002be10318}",  
  0,  
  KEY_READ,  
  &hKey)   !=   ERROR_SUCCESS)  
  return   FALSE;  
   
  DWORD   dwIndex   =   0;  
  DWORD   dwBufSize   =   256;  
  DWORD   dwDataType;  
  char   szSubKey[256];  
  unsigned   char   szData[256];  
   
  while(RegEnumKeyEx(hKey,   dwIndex++,   szSubKey,   &dwBufSize,   NULL,   NULL,   NULL,   NULL)   ==   ERROR_SUCCESS)  
  {  
  if(RegOpenKeyEx(hKey,   szSubKey,   0,   KEY_READ,   &hSubKey)   ==   ERROR_SUCCESS)  
  {  
  if(RegOpenKeyEx(hSubKey,   "Ndi//Interfaces",   0,   KEY_READ,   &hNdiIntKey)   ==   ERROR_SUCCESS)  
  {  
  dwBufSize   =   256;  
  if(RegQueryValueEx(hNdiIntKey,   "LowerRange",   0,   &dwDataType,   szData,   &dwBufSize)   ==   ERROR_SUCCESS)  
  {  
  if(strcmp((char*)szData,   "ethernet")   ==   0) // 判断是不是以太网卡  
  {  
  dwBufSize   =   256;  
  if(RegQueryValueEx(hSubKey,   "DriverDesc",   0,   &dwDataType,   szData,   &dwBufSize)   ==   ERROR_SUCCESS)  
  {  
  //   szData   中便是适配器详细描述  
  dwBufSize   =   256;  
  if(RegQueryValueEx(hSubKey,   "NetCfgInstanceID",   0,   &dwDataType,   szData,   &dwBufSize)   ==   ERROR_SUCCESS)  
  {  
  //   szData   中便是适配器名称  
  }  
  }  
  }  
  }  
  RegCloseKey(hNdiIntKey);  
  }  
  RegCloseKey(hSubKey);  
  }  
   
  dwBufSize   =   256;  
  } /*   end   of   while   */  
   
  RegCloseKey(hKey);  
  二、将IP信息写入注册表  
   
  代码如下:BOOL   RegSetIP(LPCTSTR   lpszAdapterName,   LPCTSTR   pIPAddress,   LPCTSTR   pNetMask,   LPCTSTR   pNetGate)  
  {  
  HKEY   hKey;  
  string   strKeyName   =   "SYSTEM//CurrentControlSet//Services//Tcpip//Parameters//Interfaces//";  
  strKeyName   +=   lpszAdapterName;  
  if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,  
  strKeyName.c_str(),  
  0,  
  KEY_WRITE,  
  &hKey)   !=   ERROR_SUCCESS)  
  return   FALSE;  
   
  char   mszIPAddress[100];  
  char   mszNetMask[100];  
  char   mszNetGate[100];  
   
  strncpy(mszIPAddress,   pIPAddress,   98);  
  strncpy(mszNetMask,   pNetMask,   98);  
  strncpy(mszNetGate,   pNetGate,   98);  
   
  int   nIP,   nMask,   nGate;  
   
  nIP   =   strlen(mszIPAddress);  
  nMask   =   strlen(mszNetMask);  
  nGate   =   strlen(mszNetGate);  
   
  *(mszIPAddress   +   nIP   +   1)   =   0x00; //   REG_MULTI_SZ数据需要在后面再加个0  
  nIP   +=   2;  
   
  *(mszNetMask   +   nMask   +   1)   =   0x00;  
  nMask   +=   2;  
   
  *(mszNetGate   +   nGate   +   1)   =   0x00;  
  nGate   +=   2;  
   
  RegSetValueEx(hKey,   "IPAddress",   0,   REG_MULTI_SZ,   (unsigned   char*)mszIPAddress,   nIP);  
  RegSetValueEx(hKey,   "SubnetMask",   0,   REG_MULTI_SZ,   (unsigned   char*)mszNetMask,   nMask);  
  RegSetValueEx(hKey,   "DefaultGateway",   0,   REG_MULTI_SZ,   (unsigned   char*)mszNetGate,   nGate);  
   
  RegCloseKey(hKey);  
   
  return   TRUE;  
  }  
   
  三、调用DhcpNotifyConfigChange通知配置的改变  
   
  未公开函数DhcpNotifyConfigChange位于   dhcpcsvc.dll中,原型如下:   BOOL   DhcpNotifyConfigChange(  
          LPWSTR   lpwszServerName,   //   本地机器为NULL  
          LPWSTR   lpwszAdapterName,   //   适配器名称  
          BOOL   bNewIpAddress,   //   TRUE表示更改IP  
          DWORD   dwIpIndex,   //   指明第几个IP地址,如果只有该接口只有一个IP地址则为0  
          DWORD   dwIpAddress,   //   IP地址  
          DWORD   dwSubNetMask,   //   子网掩码  
          int   nDhcpAction   );   //   对DHCP的操作   0:不修改,   1:启用   DHCP,2:禁用   DHCP  
   
  具体调用代码如下:   BOOL   NotifyIPChange(LPCTSTR   lpszAdapterName,   int   nIndex,   LPCTSTR   pIPAddress,   LPCTSTR   pNetMask)  
  {  
  BOOL bResult   =   FALSE;  
  HINSTANCE hDhcpDll;  
  DHCPNOTIFYPROC pDhcpNotifyProc;  
  WCHAR   wcAdapterName[256];  
   
  MultiByteToWideChar(CP_ACP,   0,   lpszAdapterName,   -1,   wcAdapterName,256);  
   
  if((hDhcpDll   =   LoadLibrary("dhcpcsvc"))   ==   NULL)  
  return   FALSE;  
   
  if((pDhcpNotifyProc   =   (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll,   "DhcpNotifyConfigChange"))   !=   NULL)  
  if((pDhcpNotifyProc)(NULL,   wcAdapterName,   TRUE,   nIndex,   inet_addr(pIPAddress),   inet_addr(pNetMask),   0)   ==   ERROR_SUCCESS)  
  bResult   =   TRUE;  
   
  FreeLibrary(hDhcpDll);  
  return   bResult;  
  }   
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值