找回密码
 注册
搜索
查看: 4991|回复: 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地址的详细方法介绍如下:3 _- D: a2 E+ n* W0 Z

; K. q, w, R1 Q! J一、获取适配器名称
% o7 M* s* g  }1 x; r% k
1 J: ^) n4 ?& Y这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:
- z# X% ~' b" B; u! `: O. f- Y( o' v" R0 O9 D* ~5 y! l
1.1 调用IP helper API取得适配器名称
. K. k# F' p; o- C8 e
# I. i* i1 V9 P: a9 Z9 JULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);
9 ^. E0 ?5 F4 `3 ZIP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];- N% M; g0 T0 }& P0 q% R( Q
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大/ i9 O8 G4 J2 v4 \/ }) T
{$ _; }9 R2 l2 u4 ?5 t
   delete pAdapterInfo;
/ p7 Y1 I" I8 D+ D' f- H0 E    pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
. Q5 i' H) E& F; q    pAdapterInfoBkp = pAdapterInfo;
% x- x& q7 ~, h+ E/ |1 e8 s* _}4 c6 x7 [4 W% u- e, w  \  ?2 n
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )
. A0 b( g. Y5 d- C$ A. }2 F3 ?{' G' ~: j+ q, F- @
   do{ // 遍历所有适配器
; B1 o% J9 y+ ?; ]3 E' S) b        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口0 z# ?& |( x# k2 y6 O
       {
4 h1 [' N/ _. l# v. D  C/ D            // pAdapterInfo->Description 是适配器描述9 w: {) S6 i# _7 d- Y4 h
           // pAdapterInfo->AdapterName 是适配器名称8 Q8 t) y3 ]  c
       }
) N7 R! g8 {; N! z1 C! E2 @! {        pAdapterInfo = pAdapterInfo->Next;& a  y# m: P& T6 d$ x4 F% z
   }while(pAdapterInfo);& M) Q, d- b+ t% ~
}5 z3 Y+ ^6 x2 J, \. h) E2 Z
delete pAdapterInfoBkp;: N. f5 y& B: A6 u; s# |
: Q0 u6 k, q1 j1 E) V2 i6 ]) R
1.2 读取注册表取得适配器名称; M. b0 y' k+ V9 |2 z6 j
3 N& y+ ]+ B" a. ]) x
在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;4 `6 W. J- k# o; O6 Y7 A
  Q2 j0 C5 U+ o6 Q$ w! M
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,& @: Z; x- c2 `  f/ g4 c2 n" S
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",
; @! ^  h) c$ c$ `8 U* @            0,, S6 n" n" I9 K
           KEY_READ,
+ f) E4 ]$ T: L" L  \            &hKey) != ERROR_SUCCESS)) V; O# w7 i. r* F8 J/ k
   return FALSE;+ c$ {. x+ s: C3 o

9 A  `) F! W( y2 g# q8 oDWORD dwIndex = 0;
0 c+ C$ ?$ b1 E5 c" e% EDWORD dwBufSize = 256;
1 s7 o& _7 b2 V' K/ c* U) IDWORD dwDataType;7 {% y, i6 Q# l' p5 \% p1 D+ r3 B
char szSubKey[256];" R" d2 D7 n( |/ Z
unsigned char szData[256];
8 ~8 g" ]9 W1 l0 s+ x9 Q" t4 t/ c1 v7 s$ A. z7 i: o
while(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)5 a" Z* i3 Z5 ^3 G3 \3 P1 i9 E
{
) w; i# s: I6 R& Q6 w5 i/ M    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)
1 s, b7 ^7 ~3 n    {        ; f' b" p9 |, z+ l$ i& l2 |
       if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)/ k+ Z" b. V' F8 a3 }( I1 k: v
       {8 I' s6 d: }5 g9 @( }( L1 _
           dwBufSize = 256;; n) h/ O8 ]+ c+ u
           if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
$ [5 \/ {! Y  _, l0 U+ M5 R! i            {% D+ N/ D$ m) x5 T
               if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡8 L" B4 n9 y' s: |& z
               {; G7 k3 k+ o+ T: \, |' @
                   dwBufSize = 256;
9 Z  i* ]6 y6 s+ s2 X0 e4 C' \                    if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
  K+ X2 R- L0 }+ G                    {
, i$ P! E  h: o8 `$ |4 _; X$ k                        // szData 中便是适配器详细描述
- D% ]2 V) v+ U                        dwBufSize = 256;# \1 H8 C( c/ X% G' n
                       if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)( j; l+ ]/ {1 d* g4 l$ {
                       {- y% p2 E. c' K! m& I  x: L3 R5 ?
                           // szData 中便是适配器名称9 S8 t  p, k6 G2 B& |
                       }. C1 B- ~0 n3 O7 z. A7 k
                   }) G% ?# `4 k& J7 P1 E( f
               }" \7 N4 C, w) R; [) r4 T& `, d
           }
" p+ t3 ]# ~7 v6 N/ a& \# e            RegCloseKey(hNdiIntKey);
. F0 ^1 C; C% F9 n9 v! I% k        }+ k+ h) z: j; p) J
       RegCloseKey(hSubKey);/ s: |( U- r) b! c+ ^
   }
1 X( C3 r" N0 L4 G. V( n0 _
- u: y" C1 N1 h8 a    dwBufSize = 256;
* \# z7 t0 B8 V7 v- V" ]1 n9 a}    /* end of while */$ M4 _9 P, A4 v& w0 @
       
- t! E# k5 }; D# [* cRegCloseKey(hKey);! e8 d! D* E6 W8 e9 L
二、将IP信息写入注册表. M# m/ J* A% L, {0 `" I

4 E" Y; a/ q3 H; k) |  d4 e代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
* M8 P' k# ]# y( W{
- U7 O  ^6 J9 x/ J- q4 T! {    HKEY hKey;
% `/ q9 W! s0 r' t" J) K6 B& k& l    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";, h1 a! C6 _( K; v' _
   strKeyName += lpszAdapterName;% W! @$ \$ C+ x( F# b
   if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
6 Y# X3 ~3 k; A% g                strKeyName.c_str(),
6 b5 c" U: L4 ^1 T/ K                0,) h2 G# I2 n' ?6 b# S
               KEY_WRITE,
( z! |, n0 m8 o$ P2 Q$ w; A                &hKey) != ERROR_SUCCESS)6 E& B0 O$ m. Y* h  J
       return FALSE;
, d+ R1 K& ~5 [$ p0 {( G    0 t7 S+ H9 l- G* V) S* p
   char mszIPAddress[100];4 H6 `# e7 W$ |; U4 p* n2 j  D
   char mszNetMask[100];
" `9 V' t$ C- G0 M' ]    char mszNetGate[100];5 {/ `" [1 c5 J, \4 o8 O

9 S6 Y3 B' T/ k1 A! Q2 a    strncpy(mszIPAddress, pIPAddress, 98);
# h0 b2 |( j7 {( S8 F    strncpy(mszNetMask, pNetMask, 98);
4 @# P) V5 P" I6 Q2 S    strncpy(mszNetGate, pNetGate, 98);" |3 Y: C" `3 T% ]$ [
& G3 V& v* A$ Y7 o9 S
   int nIP, nMask, nGate;
$ Z, P3 h/ _8 L& m, L, B
% [1 D' T& H! F2 z2 y7 o) f- H0 G    nIP = strlen(mszIPAddress);
: {; @0 B" D& U- h* ]' P( u: s    nMask = strlen(mszNetMask);
* Y5 T3 z" w+ I/ k) e    nGate = strlen(mszNetGate);
. a( f. b) b' `9 T0 f( K. r) b1 @+ D3 B7 ]' L
   *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0& g9 E& }6 p' b' t7 K, x; s3 Q
   nIP += 2;
' Q  n: O. ]7 j1 ~# U7 x, a3 z' I- p
   *(mszNetMask + nMask + 1) = 0x00;
! j" f3 v0 H7 E& |' J% p9 e    nMask += 2;
* y9 w2 r3 O/ R$ }% l! t$ T% L0 l" g" A4 ~, a! l; B8 V
   *(mszNetGate + nGate + 1) = 0x00;
, y8 @( v  o0 n1 a  x+ s- h    nGate += 2;3 Z# ]( B" H' Q; t" D; u
   
0 O, Q% k4 Y1 T. k$ _    RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);5 Q: k$ c' H6 c. f- P
   RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);5 n0 K+ K4 U; ^3 b
   RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);
) _% ^2 i! A, g, _  n& ~
/ C/ n) A: _; ]3 Z" q    RegCloseKey(hKey);* I6 p0 s, P3 h

7 K9 Y4 }% x7 K2 w3 E    return TRUE;3 D. M3 m( W2 h
}
8 \9 ^4 }/ M- [# @/ ?0 Y# X# S: h! V$ b
三、调用DhcpNotifyConfigChange通知配置的改变
0 S% ?1 _8 k2 |7 w
$ ?# C: ]3 Q6 Z* A* j/ k1 M未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
0 w/ i" _3 N' R2 n' r( P, s    LPWSTR lpwszServerName, // 本地机器为NULL
, i1 A  Y6 p3 E& K8 |! j    LPWSTR lpwszAdapterName, // 适配器名称
8 n" h9 [9 ?  A) @    BOOL bNewIpAddress, // TRUE表示更改IP, F& h+ B: x8 s# v
   DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0( R/ }* Z4 R9 Y: L+ u
   DWORD dwIpAddress, // IP地址
* n. M4 x) O( u# [' z. A3 [    DWORD dwSubNetMask, // 子网掩码
$ I5 A8 p! a1 u. W  Y    int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
2 P" l5 U' X( |7 u; T6 k' N- l
; o1 }. B5 L( r具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)7 C8 K* y+ h1 r9 d
{& q7 ]1 {6 {5 s8 ]) ]/ f9 k
   BOOL            bResult = FALSE;
- D! {! B: d+ n. }5 j    HINSTANCE        hDhcpDll;/ F# z% L2 Z7 f1 H1 N
   DHCPNOTIFYPROC    pDhcpNotifyProc;6 n6 @* H# o7 L" n! w3 Y! I
   WCHAR wcAdapterName[256];. M, n7 d$ w+ r  ]
   2 ]1 Z) G9 C9 n, j2 D) g
   MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
- L5 X. Z) {% C7 J( l4 }1 R, y" G. f( I
   if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL)# s% q. e9 Y) e, p1 X0 l) |
       return FALSE;0 W- p& {6 ~: v( P9 }

5 q( y' o3 \# ]9 e    if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
" M2 U1 H% l- |4 {/ S+ f& c7 K        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
% P+ C1 w( c. \$ l; @            bResult = TRUE;
) `# G7 Y, E* x6 \  _9 l! L3 t' T! v! b% D1 ~% ?$ B& c
   FreeLibrary(hDhcpDll);
: \$ n6 k2 H0 {; v5 ?9 F    return bResult;
/ P' h5 N3 K: K- w( Q) b' j* }}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

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

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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