找回密码
 注册
搜索
查看: 4545|回复: 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地址的详细方法介绍如下:6 P  c9 r: }, K; }

+ D2 d) e# x- a" M8 I$ \一、获取适配器名称$ ^2 g; Z/ _. i7 @& k' P# T7 I8 Y

, j- j; z. K5 b5 u5 E1 Y" ~这里指的适配器名称要区别于适配器描述,比如我的一块网卡,适配器描述是:Realtek RTL8139(A) PCI Fast Ethernet Adapter,适配器名称为:{66156DC3-44A4-434C-B8A9-0E5DB4B3EEAD}。获取适配器名称的方法有多种:! }8 m7 L' U) t7 h: ^7 ?6 L

. ~9 h8 I5 m0 Q* R1.1 调用IP helper API取得适配器名称 - {" C% S. c. F" b: B2 [2 \
) y& t3 M" k& X; j% x; l$ X
ULONG ulAdapterInfoSize = sizeof(IP_ADAPTER_INFO);- T, D* {0 @1 o# i+ P3 ?: l
IP_ADAPTER_INFO *pAdapterInfoBkp, *pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
) V& ?$ l, [2 {2 rif( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_BUFFER_OVERFLOW ) // 缓冲区不够大/ G- Y* P( L& O$ Y9 j! d* v4 W8 y
{9 N# @8 S$ F& ]- e- ^, q+ e; L7 `4 Z
   delete pAdapterInfo;& j' `; q/ m( d+ k* x$ a2 J
   pAdapterInfo = (IP_ADAPTER_INFO*)new char[ulAdapterInfoSize];
2 w% {+ F0 B: n    pAdapterInfoBkp = pAdapterInfo;, d" o5 x0 w. V- C( z+ \
}6 ?! E7 w2 }9 d! j: I
if( GetAdaptersInfo(pAdapterInfo, &ulAdapterInfoSize) == ERROR_SUCCESS )# K3 t0 e, v! v& z/ P( W
{
) x4 S; Q- B6 j7 K# _    do{ // 遍历所有适配器
% B: v2 M0 p) |# w6 k& L        if(pAdapterInfo->Type == MIB_IF_TYPE_ETHERNET)    // 判断是否为以太网接口
- R: q  [" L- j* P& R        {
" g' J" O7 D0 O. W+ H            // pAdapterInfo->Description 是适配器描述
6 `! h' y7 @6 b3 q7 X. {  H            // pAdapterInfo->AdapterName 是适配器名称/ O" x, d- A- Z% r
       }4 ^9 M# c" h$ c# L( G6 J% [, L9 d& I! K
       pAdapterInfo = pAdapterInfo->Next;
  d3 O( H6 g/ f0 W    }while(pAdapterInfo);
' |5 I1 l1 h' j; i* T; C}8 {; N1 m7 B+ e' \* v; X- }
delete pAdapterInfoBkp;
+ e! X* Z) r5 V
: w2 i+ T5 F- V; d1 D8 j$ n& P! H1.2 读取注册表取得适配器名称, y4 @0 O8 ?* g$ S  {! x8 Y" A
, I. g! u& z$ x4 S
在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;
6 }# z8 l! X- Z' H$ p/ r( F7 Z9 q: {3 b1 Z6 F1 y
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,3 q* @- I8 V. o5 Q3 k! a
           "System\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}",6 ]* x6 q9 l- B/ M* X0 z8 r; f
           0,
0 o. [, p0 E5 i$ d2 N1 b            KEY_READ,
  @+ z3 D. x! z4 w            &hKey) != ERROR_SUCCESS)
$ X4 z, U/ C) a8 r! H    return FALSE;& x" l% \3 a: O; U$ u1 e% {
5 ^2 X8 Z( B' P, c% N  F5 p3 q8 S
DWORD dwIndex = 0;
$ `* k; @7 I5 j2 F( q) m2 S8 yDWORD dwBufSize = 256;
) O1 K+ |$ H8 T7 O$ kDWORD dwDataType;- z1 }" f3 m6 z& L7 o
char szSubKey[256];
+ |4 U& ^& B5 y6 X# p6 iunsigned char szData[256];
( f0 [# u  W' U$ E) w* Y; H# s% }
1 ]( W2 L/ j6 Nwhile(RegEnumKeyEx(hKey, dwIndex++, szSubKey, &dwBufSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS). r# L# ^. W* _. o+ x
{
0 l; J' `+ w5 ]& }' e1 V7 X+ v2 q    if(RegOpenKeyEx(hKey, szSubKey, 0, KEY_READ, &hSubKey) == ERROR_SUCCESS)" z) K' x. i( \, V5 N5 i) q- c7 _
   {        
& _/ D" _3 U; F2 H1 \2 e: x        if(RegOpenKeyEx(hSubKey, "Ndi\\Interfaces", 0, KEY_READ, &hNdiIntKey) == ERROR_SUCCESS)8 x* b9 w! j5 n3 r7 g# s
       {8 J9 o4 j# I8 E" t% y  R
           dwBufSize = 256;
0 |  j" Y0 Y% X* y/ W            if(RegQueryValueEx(hNdiIntKey, "LowerRange", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)5 v$ f2 |% o7 R2 I
           {
8 q7 a/ B4 z4 g3 M# ?2 K5 p; T                if(strcmp((char*)szData, "ethernet") == 0)        //    判断是不是以太网卡
4 o% i. o- y* k7 Q4 d2 I5 h0 R                {( |7 b' ~/ T, V3 e
                   dwBufSize = 256;
7 L  {& j' N% y, W                    if(RegQueryValueEx(hSubKey, "DriverDesc", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
8 d3 P9 ~; a& C, d1 O8 g                    {) I# J- u' g  k* s. Q/ t, Q  k
                       // szData 中便是适配器详细描述
( ?' f1 ~; G9 J, a  w2 M                        dwBufSize = 256;
6 J/ G3 q$ g3 ?" d) K                        if(RegQueryValueEx(hSubKey, "NetCfgInstanceID", 0, &dwDataType, szData, &dwBufSize) == ERROR_SUCCESS)
$ C$ I- M1 `3 Y3 E                        {
- N! k2 K& I8 p1 Q                            // szData 中便是适配器名称1 I& u0 [2 W2 @# V. Z. g
                       }
8 y) D: n% U* Q  s                    }
( l( e1 z- _% x  `' t( \                }
6 L1 Y3 k% ]) N# b7 Z0 @# r            }
. \1 {) L8 @3 K" C            RegCloseKey(hNdiIntKey);
! S& }9 R: o- |6 a% ^8 z        }
* y2 q9 |+ ?$ u3 \* E$ q        RegCloseKey(hSubKey);
- A" E& p7 k2 f8 y    }# `' g( y/ S. z3 ^

4 _4 I( r/ ]" Y; ~- ~& D4 [    dwBufSize = 256;& [  s9 F* S- `( }" _1 K
}    /* end of while */
" F5 g8 G6 y! k4 b! }5 }        
- @7 V1 j9 k4 m% E, Y$ {) }/ lRegCloseKey(hKey);5 @, K% }8 ?5 v4 V
二、将IP信息写入注册表* {# y! ~6 [" d
9 O! i. g) t$ ]8 Q3 y9 h, D
代码如下:BOOL RegSetIP(LPCTSTR lpszAdapterName, LPCTSTR pIPAddress, LPCTSTR pNetMask, LPCTSTR pNetGate)
- b$ m2 S7 U8 q1 t; D& ?{7 b, F6 }9 e7 v' F
   HKEY hKey;
* x. A. W: }) B" |    string strKeyName = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";. v/ m; h. d/ d7 C' ?! l" U
   strKeyName += lpszAdapterName;
/ h2 Y7 D4 ]. Y; p% v% U$ u    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
* p9 a5 X. ], V" z2 M/ o                strKeyName.c_str(),
- X9 B4 S# F8 J$ Q                0,) J8 r; t2 n0 }* X! R1 ?/ w
               KEY_WRITE,6 f' w/ L5 b1 |( i5 G
               &hKey) != ERROR_SUCCESS)
8 b, k3 D1 P: C3 O8 z1 c( {        return FALSE;
' c/ r& \- @- A: W. O( i0 X3 D    - W8 t, \. s! {' E2 v, u% x$ ~
   char mszIPAddress[100];
- }! _" _8 H' r; R- v    char mszNetMask[100];
) h9 M, N; [9 _6 B3 ?0 U    char mszNetGate[100];
$ b2 Y' X. [. U# _; `
4 D9 R! @8 E* _( p* V  f! ~    strncpy(mszIPAddress, pIPAddress, 98);$ k0 H- \) s, o
   strncpy(mszNetMask, pNetMask, 98);
" S2 p/ J# c5 E" U! k8 M    strncpy(mszNetGate, pNetGate, 98);
  d9 N. T* A# q  y5 l* g6 d' H( ]3 S' a9 U+ ?' L4 _% ^; @
   int nIP, nMask, nGate;
2 A7 F! a' ?( }: f, _! @4 T, ~: J- h0 a2 Y
   nIP = strlen(mszIPAddress);
4 e; O( @0 A! ]' Q2 U    nMask = strlen(mszNetMask);
# V# a/ V2 u- w7 Z    nGate = strlen(mszNetGate);
( F( ?/ z. R# ]+ _) d, Z& V
* i. ~$ A$ a+ D) H' H  ^  m    *(mszIPAddress + nIP + 1) = 0x00;    // REG_MULTI_SZ数据需要在后面再加个0
  w+ }  U* v4 Q+ T. @3 K. z) h    nIP += 2;
' H6 t3 C7 L2 {2 G- |3 _1 o' O* c( B6 D$ t, w- h) }
   *(mszNetMask + nMask + 1) = 0x00;$ s* a! ]2 u( w. A" i+ A
   nMask += 2;
6 O" m. S: N! J0 T- q7 g! {* Z- N
3 m5 j5 p- E6 Y+ g7 S" |2 I    *(mszNetGate + nGate + 1) = 0x00;
+ D3 C6 G& i: H  _+ K: Z3 X) n    nGate += 2;) ?: G7 ^, y9 m8 x1 ?
   ! f6 \8 g1 \; f* P3 v
   RegSetValueEx(hKey, "IPAddress", 0, REG_MULTI_SZ, (unsigned char*)mszIPAddress, nIP);
4 j5 ]2 x( w7 M- l) d5 r/ l* D. b    RegSetValueEx(hKey, "SubnetMask", 0, REG_MULTI_SZ, (unsigned char*)mszNetMask, nMask);
9 s1 V# a( {6 h$ d9 n0 \    RegSetValueEx(hKey, "DefaultGateway", 0, REG_MULTI_SZ, (unsigned char*)mszNetGate, nGate);. ~0 ?9 m% G' H# s/ T: J/ j
" x* \4 [4 Q. p. l$ Q# D& k
   RegCloseKey(hKey);
- ^/ `  G; P+ y* ]+ U- ?& U! j. d& U/ h& p1 e* f
   return TRUE;$ }3 N2 k' e6 `' T$ h1 c% B/ M
}6 B" ]; P; `6 V" y8 Y$ k- G1 f0 u  e4 y

5 e& b0 k  P  s# _4 G" v7 Y三、调用DhcpNotifyConfigChange通知配置的改变; C5 _! e' G8 m; r* R% n: x1 V& Z
& x, S1 a) Y8 y3 d5 l4 n
未公开函数DhcpNotifyConfigChange位于 dhcpcsvc.dll中,原型如下: BOOL DhcpNotifyConfigChange(
1 N4 {& X0 I: B& \, e- r    LPWSTR lpwszServerName, // 本地机器为NULL0 X- q, g( ?& O! x" D8 r+ d# [
   LPWSTR lpwszAdapterName, // 适配器名称
+ T* Z9 t6 D; b4 d/ T0 T( `8 r    BOOL bNewIpAddress, // TRUE表示更改IP
; k  U& N1 Q& s% N    DWORD dwIpIndex, // 指明第几个IP地址,如果只有该接口只有一个IP地址则为0
& j) H( k$ Z$ M$ I7 E& E    DWORD dwIpAddress, // IP地址6 t$ W; S! N1 I4 k0 Q$ W5 w
   DWORD dwSubNetMask, // 子网掩码
! s9 @( @- w+ l7 ]! I: f! v. X5 u    int nDhcpAction ); // 对DHCP的操作 0:不修改, 1:启用 DHCP,2:禁用 DHCP
( y" }! m, R2 H$ j3 ?9 d8 P9 e/ a1 p. Q5 m% ]( h
具体调用代码如下: BOOL NotifyIPChange(LPCTSTR lpszAdapterName, int nIndex, LPCTSTR pIPAddress, LPCTSTR pNetMask)
7 ^; l; y5 z% ?{
6 d1 Y& p( e; U; d5 Z) P    BOOL            bResult = FALSE;
$ G& \5 ]( I: g! ?5 @7 U% g    HINSTANCE        hDhcpDll;% w2 D) d- }; t  J% K# N9 {
   DHCPNOTIFYPROC    pDhcpNotifyProc;0 g  k. Q1 |$ g  a7 }
   WCHAR wcAdapterName[256];# u, P' N$ j& f2 u# x% S3 R3 H% q4 H4 V
   5 r; N/ G" t9 Y9 X
   MultiByteToWideChar(CP_ACP, 0, lpszAdapterName, -1, wcAdapterName,256);
8 B3 x1 p- Y, V) j, s' H
/ f: P4 R: j9 G    if((hDhcpDll = LoadLibrary("dhcpcsvc")) == NULL), Y4 p& `( ^5 k6 h( B
       return FALSE;
2 A1 V9 u% r2 e- ~, T; Z6 q+ W; U/ I' H5 u
   if((pDhcpNotifyProc = (DHCPNOTIFYPROC)GetProcAddress(hDhcpDll, "DhcpNotifyConfigChange")) != NULL)
+ g8 M; F" E3 t9 r$ w/ z+ I0 U        if((pDhcpNotifyProc)(NULL, wcAdapterName, TRUE, nIndex, inet_addr(pIPAddress), inet_addr(pNetMask), 0) == ERROR_SUCCESS)
# l0 c: p" J- {1 |            bResult = TRUE;, Z. J4 |- ?4 u3 E' Q4 D' S

! Z# R, @- z4 F/ ]2 C6 k    FreeLibrary(hDhcpDll);
* Z0 X4 G( H5 L0 ]' e    return bResult;
/ f: A/ @# s8 P/ Z. L# \* Z}
发表于 2005-7-26 02:44:28 | 显示全部楼层
楼主厉害 我只知道 改了IP后 禁用网卡 在启用 就算在win98都可以不重起让新IP生效
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-6-19 12:28 , Processed in 0.015389 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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