找回密码
 注册
搜索
查看: 4992|回复: 1

[收藏]Windows NT/2000更改IP地址不需要重新启动就可以生效的方法探索

[复制链接]
发表于 2005-5-24 11:03:31 | 显示全部楼层 |阅读模式
  设置IP地址只需要更改注册表中关于适配器的相应设置,但更改后需要重新启动系统才能生效,而AddIPAddress函数只能添加IP而不是更改当前的IP,我们在Windows NT/2000界面上操作不需要重新启动就可以生效,那系统到底做了什么额外的工作才使IP设置直接生效呢?笔者通过跟踪explorer.exe中API的调用发现在netcfgx.dll中调用了dhcpcsvc.dll中一个未公开的APIhcpNotifyConfigChange,现将不重新启动WINDOWS直接更改IP地址的详细方法介绍如下:
+ X8 |+ M* T3 \* y1 M7 s1 b5 r6 u/ e9 n! I
一、获取适配器名称
+ U7 q$ ?0 @8 Y2 D% F- t* B1 i
) L. w: ]: i3 n9 h* g9 P这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
1 h' g0 E3 ]; y1 I& ]" d- X
9 I! _; P* R- L: L; b1.1 调用IP helper API取得适配器名称 $ h+ @1 l, C9 A! m

" m) n9 b8 k+ B, l) ~& o# ~ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
, w) ]4 `) V. g: v6 |3 z/ MIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
: b, P1 Q6 g! O) c/ {2 yif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大
# Z9 D8 ~* d/ Z$ p: W& X{
# O! E& p$ r) }: j    delete pAdapterInfo;
1 S( ]. _- p! Q; G) [5 P    pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];. o6 F2 a) C- e
   pAdapterInfoBkp = pAdapterInfo;. Y! y4 d1 ~6 v/ X7 L
}" |4 l$ q% F$ H" {3 a/ Y
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
& \$ [  h6 {/ q( r2 J0 ~{
% ~& E4 T: ~6 ^3 A6 a. f  a4 \    do{ // 遍历所有适配器
* o) e0 G: E6 x' u' X        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
- U2 F. e- V' t5 B- K7 g6 g        {
1 p0 C! C0 D0 s$ [4 {6 x            // pAdapterInfo->Description 是适配器描述
5 U; u4 w, q' F& b            // pAdapterInfo->AdapterName 是适配器名称# p1 k$ X4 ^1 B2 z* t5 o" @
       }
' G7 ^% {+ I$ |: f4 G        pAdapterInfo = pAdapterInfo->Next;
! Z7 C8 I1 A8 Y( g3 r    }while(pAdapterInfo);
9 f: u- [/ M' m/ r2 ]3 }& W}) ^/ c  X: s5 o6 ?: j6 s' g7 d
delete pAdapterInfoBkp;
6 J) ?$ M+ V: ]- d
) ^4 a% P5 N6 W8 ~" `8 G3 [  c1.2 读取注册表取得适配器名称
* V2 `& K7 \6 h4 C" t6 [
* d! ?1 d" a& W6 f. S' P, I在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;' u, K2 e; |* ~) R7 @1 a
6 k/ [% s4 I# @" T* w! x# |
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
' P8 }" H' H1 F4 a5 w' L. I            "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",' F: M' }& ^/ E4 G
           0,9 \# h: }+ O8 j+ U+ h
           KEY_READ," P( F8 a, w$ ]9 v
           &hKey) != ERROR_SUCCESS)5 Z6 ?/ [% R: [7 R7 N% T% p8 ]) Z
   return FALSE;
3 g/ Y9 U+ A7 i6 _3 b8 J  S  }* n1 Z' {5 D& H% O3 Q
DWORD dwIndex = 0;) l4 _0 B9 R* j5 p! c5 y
DWORD dwBufSize = 256;' X6 W1 u; x$ C+ }/ l# C
DWORD dwDataType;
/ @3 c) c% b+ p% ~' F' echar szSubKey[256];
2 t! I9 Z0 C' `' Runsigned char szData[256];
8 \) E6 Q5 h& j) |
& R) t8 j# f6 X: D4 Nwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)7 c  H" N- z+ h# }' j& H
{( t' b( ?; K5 X7 @5 j, `8 @
   if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)% Z7 K1 p5 x. Y, Z' v
   {        ' Z5 w+ Z, ^- a# p* a7 J9 ^
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
$ Y9 X; @7 Z+ {8 Q" m        {6 q7 P% k' J& |* k% m0 ^
           dwBufSize = 256;' a- p: s, a) A7 b' @5 m
           if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
+ f; Y9 b/ `* P7 k. ?% g2 \            {6 T* q: t! Z5 c5 U* Y
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
0 d1 C) W9 E* c' x( W6 X                {
. z+ G/ X: H; L7 I  s                    dwBufSize = 256;$ ^: R3 b% G1 x" o4 e
                   if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
( j( y, j' m! u8 c+ b  O7 ?7 _7 K- h; k                    {
8 T& g) e6 {) D, k) t; H  x$ s                        // szData 中便是适配器详细描述
9 H/ L5 g; q5 Y6 T/ s0 {                        dwBufSize = 256;  h2 `' F& Q/ l) q7 f7 x2 O. o
                       if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)$ e" n, W$ V& d  }# g
                       {) ^* m; b+ e9 N! n2 {5 f
                           // szData 中便是适配器名称
+ g. ?3 [6 E1 s& w+ m  [! R- }                        }
" x8 B+ P* J" V; T- t- O. ?1 ^9 y                    }2 v; c) h* d7 z- R" j2 c
               }6 B$ I6 S9 [* D+ X( X. z
           }
! T: J& c# ?/ `; l5 ]            RegCloseKey(hNdiIntKey);
% Y  X3 i+ r# x" u, o        }
7 N! @0 U9 L) H" O) f- f1 V        RegCloseKey(hSubKey);* q( e( l  ~1 L. J& U, a3 ~
   }6 `4 e, [8 x' ]1 {. i
! H$ N# S! a  U# M; D
   dwBufSize = 256;+ N1 s3 m% Q9 l* T
}    /* end of while */; S7 o% n# E! v* h/ w- p, ?
       " v6 C; q% f, ]* Z
RegCloseKey(hKey);6 \8 e* L) k: [, A2 J; n7 r3 F7 ~! j
二、将IP信息写入注册表2 Y9 f. m. ^  I

/ p7 ~3 z/ i: Q; C5 `+ T代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
, l1 O% o* _- W# U! }4 \- N{
" p5 r2 x; Q2 O) x1 P4 }8 i    HKEY hKey;
. Z6 v$ ]% j5 }' |3 z    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
2 w( k' F* j) F! v2 K    strKeyName += lpszAdapterName;
- Z: K7 G6 @: u    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
5 h7 e  @% X% P5 r8 U                strKeyName.c_str(),8 G) T; i5 z3 _) _' I6 O
               0,
. y( ?/ y( q# C% ^                KEY_WRITE,
  f% L! e& k' @. @" `1 B                &hKey) != ERROR_SUCCESS)
3 n$ `2 Z+ n: Y# C        return FALSE;( m3 \1 v: V7 k2 A; _2 V+ K- C* x
   
7 j' m+ \( p6 X( `" u& }) W    char mszIPAddress[100];; ]2 ^# y+ T. ~4 d) _% m' t& y
   char mszNetMask[100];
$ p! x4 S+ z& p  e6 P    char mszNetGate[100];" z5 `7 D* v1 e# g' B% y. h: K; N
& a; W1 _& j# ]5 F
   strncpy(mszIPAddress, pIPAddress, 98);
8 o8 N- S/ s, g4 z2 Q    strncpy(mszNetMask, pNetMask, 98);. n0 n- ?% p. L: K% d
   strncpy(mszNetGate, pNetGate, 98);9 `3 x2 a0 j* H. F
' W$ p4 w4 o5 M. R9 N
   int nIP, nMask, nGate;% X  d; s  y. c$ }" g  L
5 v9 o3 |6 A- r! s, w
   nIP = strlen(mszIPAddress);- f0 ]$ f* j) _4 r! j' I6 z
   nMask = strlen(mszNetMask);
, R0 d+ |( Y- d4 G/ X% I; U    nGate = strlen(mszNetGate);
4 {) m5 Z, @$ @0 [2 ]1 m8 f
# ?8 @2 g5 h! g2 a! s1 |. q    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
. k/ K3 ]- M( B- ]    nIP += 2;
* F% x6 m0 x3 w& n; \4 N" E! d3 _
   *(mszNetMask + nMask + 1) = 0x00;! C4 [, u: y5 c8 @9 i+ r% s
   nMask += 2;1 R! b% |) g  q2 |
+ K* K( v+ [6 i0 M1 x* C0 n
   *(mszNetGate + nGate + 1) = 0x00;  d* Z* [: E5 `
   nGate += 2;2 a% g) U) e4 G- ~
   ' O# u& D: a8 l. Z. m
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);' V6 h! z4 k! P, h: F8 P6 X) y/ K4 Z- X
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);. `9 @# q: V4 F' Q* @* l
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
/ O: G, P1 |) ~1 Y" g; _( L- F& S( G7 p! p0 z, D# D
   RegCloseKey(hKey);
0 m5 Z3 w' j. ~7 W3 g: _. D" g; L9 F7 P
   return TRUE;7 z8 t  E0 e' @+ }) d& }
}& j( P" E/ `% U2 u7 V

1 K' R$ f0 n9 Q6 |2 G三、调用DhcpNotifyConfigChange通知配置的改变
4 ^' f7 N8 `" f5 \" ]
9 Z3 _2 C( Y8 P* ^; ]  u2 @未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
  f3 c& R, l1 @8 f9 Z) [& ]    LPWSTR lpwszServerName, // 本地机器为NULL
1 C! D" e7 J3 g4 I7 E    LPWSTR lpwszAdapterName, // 适配器名称
4 x/ U. ]( u* v" f    BOOL bNewIpAddress, // TRUE表示更改IP. t. }$ Y: M) G) k: y/ y" w
   DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0. K2 C* H7 R- y7 P: v$ G1 X
   DWORD dwIpAddress, // IP地址; a( V. h) l/ B, A' f% E
   DWORD dwSubNetMask, // 子网掩码" H# P# {' ?9 q' H0 I
   int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP1 [# B8 Q, C) T: h! C1 i* P

% g. Z; {9 q5 e4 U% _具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)- q/ r- y  B7 ~2 v2 F
{& X* a' A9 ?3 E  S
   BOOL            bResult = FALSE;
+ |, }5 R" N/ H# Y    HINSTANCE        hDhcpDll;
% O3 c+ C: \7 |) P5 ?9 T. x5 e! [    DHCPNOTIFYPROC    pDhcpNotifyProc;4 W) @/ m- s; U, ]( P# F& t1 Q
   WCHAR wcAdapterName[256];
3 V0 ~) N% }0 y* r: s* V    ; U1 |# _/ w9 b2 r
   MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);! w; L0 Z% A$ ?* H$ ]& Y
2 }5 S* C( H  E# ]7 \
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)4 A" B0 T9 h- I8 X+ ]8 Q) g7 G' g
       return FALSE;' Z* k. e! U- `3 }( ?7 |( {9 t) Z3 o$ j
  `) R# B) G7 m" H
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
5 ]" [" G4 G- @5 n3 e        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
- b3 o* e) p  Z+ t! V. A+ o0 P            bResult = TRUE;
7 }4 s( B; o$ |* t) {; R4 }6 |5 b$ f9 u% v
   FreeLibrary(hDhcpDll);* D6 D8 A- Q+ t3 I# D7 `7 f$ z
   return bResult;! h0 m# a( H3 j3 V
}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2026-6-18 09:05 , Processed in 0.020101 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表