找回密码
 注册
搜索
查看: 4933|回复: 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地址的详细方法介绍如下:
8 \: ]9 u8 S" c' D% i& x% D+ e; h8 H/ I' ^7 Q, a
一、获取适配器名称
/ [# D. ^& \2 Y9 J) x! i; G) u6 F  b
这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:; x) [5 o) V8 C4 ^2 p
7 ~0 c4 C9 z/ X& Q
1.1 调用IP helper API取得适配器名称
6 R+ f' f  e( u9 I
- y" {7 d! F, }  a; \) ~ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);4 z9 E* ^9 z6 ?
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
8 m/ J7 g; K. R8 oif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大/ L7 W5 M$ R1 T9 P3 S1 B& D( a
{" a1 @! K" c1 |+ h
   delete pAdapterInfo;* D# S) e' b" f' ]! ]9 Z
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];4 @' K! q4 }- V: F
   pAdapterInfoBkp = pAdapterInfo;
0 S, m5 v( I- ]8 b$ W3 M( D, ]}
4 }% w+ m& ]& K7 K( dif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
7 T% n7 _" z2 i+ G4 Z{
/ s" `9 r( ]7 m. w1 m    do{ // 遍历所有适配器
, S5 h$ l) c. {# }" X: V        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
9 ?% r! g$ \$ _' ]/ K$ @) J        {4 x. ?$ _# j0 P3 |+ ]
           // pAdapterInfo->Description 是适配器描述) ]; w! B6 R% F) x0 y; C* m
           // pAdapterInfo->AdapterName 是适配器名称: Q7 T' o0 F) b# h
       }
: v" I: K. g* s; f* @% l9 o2 z        pAdapterInfo = pAdapterInfo->Next;
% m& H! I7 ]: b" Y2 ?3 `3 @    }while(pAdapterInfo);6 |+ m! O7 \1 o  i
}
" ?. o6 A& x& k# Sdelete pAdapterInfoBkp;8 f  n2 D/ L  T: R) F; t

) s# I4 Q, [+ ?0 N1 ~0 ~* h& E5 Y: z1.2 读取注册表取得适配器名称! Q; u* M& K9 H# q  N' i( {; q

& T/ x/ K- E% `: F) p在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;
+ o3 O: ^; R& p: T+ L  J
% j, x; @* W7 K; Bif(RegOpenKeyEx(HKEY_LOCAL_MACHINE,6 }# B/ d1 R" z! U7 `" h! L
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",% H6 o% J  c3 O& J' \
           0,
# c0 }. o, L/ j9 q4 D% M" m/ L. Y( x            KEY_READ,- P" A5 K4 \  O4 U. z1 B/ [+ [
           &hKey) != ERROR_SUCCESS)& r1 t* z8 `' ?; F# `, J
   return FALSE;4 ]' O' N# G4 N

( D6 k7 O& i, fDWORD dwIndex = 0;; @6 M5 C# U" F
DWORD dwBufSize = 256;, Q; h* F- ?! y$ V7 B
DWORD dwDataType;
  _7 Q1 d, d2 m3 m. {char szSubKey[256];) M" P+ N- C/ }8 \' p
unsigned char szData[256];, s# s+ c1 G4 c# f5 l( s
% R) ]9 ]; s% K5 ?4 m$ D- g4 l0 Y
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)' z8 [( N6 \0 w$ d' l/ @8 X2 @
{6 K4 [, o/ K" @4 M* s# m# V9 ]
   if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)$ B& ]0 e, y4 j6 X0 C
   {        & \8 g, L! K2 M3 l5 L- Y9 b4 @
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)
2 L! h; }& s1 T) R- l# L! L, B5 a        {
7 A9 _6 c# L: r5 h$ G& l- K            dwBufSize = 256;
! u8 u/ _* E+ H5 F* H" c            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  G4 r$ ^1 R8 J6 N4 [- A  Z            {
! D& ~' j9 D1 C) ?                if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
/ ~! T  L: t" v                {6 _9 H3 F% J: ~; c3 w0 u7 J
                   dwBufSize = 256;
$ _2 y/ m, \4 _' Z0 Y, h                    if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)) t$ h% t, ~" M- p+ S- t( M
                   {6 t- Z+ y4 F1 v: c
                       // szData 中便是适配器详细描述! a8 l2 s- l1 h1 `  r
                       dwBufSize = 256;
- S( j" q" X" A6 d$ l( W                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  f& g6 o; j6 w4 B# H                        {
9 z7 h7 L* P9 o% @" ~2 ?                            // szData 中便是适配器名称
/ G" ^* K8 A! T1 z$ ]9 H- D# ^' ~                        }
" d- t1 ^4 A" B% T* I) @                    }( _2 C8 S5 Y  Y+ X, V% U
               }
& x. M! V: [/ N            }
: g( o% W. p/ E3 ^1 g            RegCloseKey(hNdiIntKey);
! Y3 l  ]" ]  W" a) d  Y2 p        }
5 ]; s$ r' A' K  k5 }        RegCloseKey(hSubKey);
  Z1 F5 L5 ?9 H- v    }
$ }& M) I- q( a2 m
6 p4 R" L8 `6 @! i7 m1 a# n    dwBufSize = 256;) |, e" l+ c- X' n9 H* h# g9 K
}    /* end of while */+ j9 f8 J( c7 d0 c5 w0 Z5 Q( a4 ^* C8 H( ~
       
4 L9 R  `% c3 J5 W3 D: a& u/ pRegCloseKey(hKey);; `* ~) c- V  J
二、将IP信息写入注册表" D. N) P$ ~/ o$ E  E5 V0 |
3 n7 s* S$ d! f* k/ O
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
. X& I5 l( a; a; [$ W8 ]8 w' M9 o{; L/ I* Z; k, W% B% A3 W5 h
   HKEY hKey;, \( j, n; Y+ D
   string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";/ I3 B' n3 |! e* L  p
   strKeyName += lpszAdapterName;
5 K4 O6 S, ?" n+ O9 h    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,0 q$ s+ |- A8 o6 C" ?3 K
               strKeyName.c_str(),
' o# h1 W8 }9 t4 R# \                0,
8 Y" N" z6 u) x8 e' }+ u                KEY_WRITE,
# m1 x/ }6 L# K8 M* V5 A6 a8 n                &hKey) != ERROR_SUCCESS)
, d+ V1 Q2 T; ?) x        return FALSE;0 N9 m4 q: H; f. L4 f( l  r
   
# y0 L# x! g7 m$ o    char mszIPAddress[100];
' x% ^4 q, [8 ?. @4 E- R    char mszNetMask[100];
4 p( F8 d6 C) w* x0 h( e    char mszNetGate[100];7 E# B8 ?  y$ Y& f/ o

, Z' N1 d: v+ m9 j" Z5 z    strncpy(mszIPAddress, pIPAddress, 98);
! p; c/ M9 u) d- T5 M! S; X8 q    strncpy(mszNetMask, pNetMask, 98);
* F/ Z* _: J& I, V; o" {; V. y! ?    strncpy(mszNetGate, pNetGate, 98);/ t' r0 Q! X: E$ Z5 I7 j; z( _

' t2 g& }- |5 ?/ I( n. x3 c8 B    int nIP, nMask, nGate;
/ s  l& o9 C$ v. L" l& v/ K! J0 }9 A& z  I! L! _) b" {
   nIP = strlen(mszIPAddress);
0 U3 w, [: `7 N3 S( g  K9 G5 c    nMask = strlen(mszNetMask);
$ M+ m/ p4 Q& s    nGate = strlen(mszNetGate);
" [1 ~  T0 M5 K& Y; r/ Z
: D$ z5 Y: l. M( O3 w) U    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
; u3 ]) f- w7 z    nIP += 2;8 `7 s/ @, K) {5 L  L+ N
' l& i3 q/ M7 W, w1 @6 ~
   *(mszNetMask + nMask + 1) = 0x00;
/ a# K2 J9 E1 b: i( `    nMask += 2;. y1 j0 s2 L0 ]" X2 s

6 |' z4 b+ i+ X5 c7 R    *(mszNetGate + nGate + 1) = 0x00;
$ |& l) r6 ], N    nGate += 2;
5 q1 y! ^% E$ F2 o    ' L. `, V& i, d' m
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);9 Q. q( I) V4 d" x  B8 d$ P
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
: A; J6 U" i: q0 w+ K" x" y5 S    RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
6 N8 D7 n4 o) s1 r' f- H- f+ T! W' h) P
   RegCloseKey(hKey);
2 @; w1 W: {5 B  z; r" `% P
) I( z2 u7 |( l    return TRUE;  V0 n- P# G& N
}  ?9 O/ B, e) L; P# J) Y
; R# Q* u+ U" J
三、调用DhcpNotifyConfigChange通知配置的改变
4 D: F4 c5 U$ I5 I
, S* D5 i& E) W+ H. G: q未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(, P9 B  B# S7 \+ Y# y$ e+ {' v( k
   LPWSTR lpwszServerName, // 本地机器为NULL9 `; j% g& S# Y) G, @, a! `/ u
   LPWSTR lpwszAdapterName, // 适配器名称8 U+ P" D% K+ H  d/ q$ f8 O0 F4 L* O
   BOOL bNewIpAddress, // TRUE表示更改IP% C* p0 [7 L+ y7 O+ v
   DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0% _& l# M: X1 S% E/ r9 e
   DWORD dwIpAddress, // IP地址
) g, N9 m$ D' B5 _" P    DWORD dwSubNetMask, // 子网掩码
9 h, `' j% B1 l, c3 D) e  `& E2 [    int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP7 S7 l6 L& Y9 l4 |

% O3 r( L  `/ y5 ?0 u; y具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
9 a: i" Q9 c- W* a- h# I{
9 F) e. q4 T* e' |* `4 W    BOOL            bResult = FALSE;
+ ]  X. T! a' I( G( X    HINSTANCE        hDhcpDll;' G8 `/ Q; ~9 n7 u$ k# a7 ~5 ~* R
   DHCPNOTIFYPROC    pDhcpNotifyProc;
+ W; R+ y/ r% |1 [    WCHAR wcAdapterName[256];
' E+ J; p- Y4 G2 A7 I    
7 D0 e4 E6 s$ @# A' q( C+ Q    MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);, F5 u1 e" H/ j* d7 Q8 T# c

; w4 G1 Z  s/ d  M# ]  g    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)& A  Z2 o; O. `+ v- F
       return FALSE;
/ _9 l7 x: m2 J4 }4 Z2 u2 m+ `& Q4 M2 C, _* ^
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
- n* @' b3 W4 q) W# H        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
3 N$ y. P/ F7 v2 i            bResult = TRUE;' W4 A1 U/ h% v5 ]
' e0 A! M6 w& Z
   FreeLibrary(hDhcpDll);# Y; F' J/ K1 {, D8 F
   return bResult;7 K. p5 Y4 G/ E
}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-5-2 10:32 , Processed in 0.017972 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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