在程序中修改IP win7 winXP(参考1)
https://blog.csdn.net/bbdxf/article/details/7548443
Windows下程序修改IP的三种方法
以下讨论的平台依据是Window XP + SP1, 不考虑Windows其它版本的兼容性问题, 但对NT系列的系统, 理论上是通用的.
方法一: 网卡重启
更改Windows网卡属性选项中IP地址, 通过对比前后注册表, 可以发现以下几处发生变化
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}]
"IPAddress"
"SubnetMask"
"DefaultGateway"
"NameServer"
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip]
"IPAddress"
"SubnetMask"
"DefaultGateway"
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}]
"IPAddress"
"SubnetMask"
"DefaultGateway"
"NameServer"
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip]
"IPAddress"
"SubnetMask"
"DefaultGateway"
其中{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}是网卡名称(AdapterName), 不同的网卡, 不同的接入位置, 不同的接入的时间, 对应的值都不一样, 它的值是第一次接入系统时, 由系统生成的GUID值.
此处CurrentControlSet实际是ControlSet001的别名.
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}]
"IPAddress"
"SubnetMask"
"DefaultGateway"
"NameServer"
是主要的设置处.
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Parameters\Tcpip]
"IPAddress"
"SubnetMask"
"DefaultGateway"
对一些服务有影响, 如不设置, 用netstat可以看到原来的IP地址仍处于监听状态(?).
但为了使设置生效, 还有很重要的一步, 即重启网卡.
更改网卡的配置, 一般而言需要重启网卡, 如
Linux系统, 只需运行
#ifconfig eth0 down
#ifconfig eht0 up
就可以实现网卡的重启.
Windows环境下的步骤与之类似: 先禁用本地连接(网卡), 再启用本地连接(网卡). 但没有相应的命令或者直接的API. 所幸的是DDK提供一套设备安装函数, 用于控制系统设备, 包括控制设备的状态改变.
/****************************************************************************************
Purpose: change state of the selected device
Input : hDevInfo device info set
pDeviceInfoData selected device info
NewState one of enable/disable
Output : TRUE for success, FALSE for failed
****************************************************************************************/
BOOL ChangeDeviceState(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDeviceInfoData, DWORD NewState)
{
SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)};
SP_DEVINSTALL_PARAMS devParams;
if (!pDeviceInfoData) {
return FALSE;
}
PropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
PropChangeParams.Scope = DICS_FLAG_CONFIGSPECIFIC;
PropChangeParams.StateChange = NewState;
PropChangeParams.HwProfile = 0;
if (!SetupDiSetClassInstallParams(hDevInfo,pDeviceInfoData,
(SP_CLASSINSTALL_HEADER *)&PropChangeParams,sizeof(PropChangeParams))
|| !SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,hDevInfo,pDeviceInfoData)) {
return FALSE;
}
reutrn TRUE;
}
/* hDevInfo如何得到***********************************************************/
m_hDevInfo = SetupDiGetClassDevs(
(LPGUID) &GUID_DEVCLASS_NET, /* GUID_DEVCLASS_NET表示仅列出网络设备 */
NULL,
this->m_hWnd,
DIGCF_PRESENT);
if (INVALID_HANDLE_VALUE == m_hDevInfo) {
return FALSE;
}
/* pDeviceInfoData如何得到**************************************************/
k = 0;
while (SetupDiEnumDeviceInfo(m_hDevInfo, k ,&DeviceInfoData)) {
k++;
if (CR_SUCCESS != CM_Get_DevNode_Status(&Status, &Problem,
DeviceInfoData.DevInst,0)) {
continue;
}
if ((Status & DN_NO_SHOW_IN_DM)) {
continue;
}
if (GetRegistryProperty(m_hDevInfo,
&DeviceInfoData,
SPDRP_FRIENDLYNAME,
&pBuffer,
&Length)) {
m_Adapter[adapter_num].index = k - 1; /* 当前网卡在设备信息集中的索引 */
_tcscpy(m_Adapter[adapter_num].desc, pBuffer); /* 当前网卡 */
GetRegistryProperty(m_hDevInfo,
&DeviceInfoData,
SPDRP_DRIVER,
&pBuffer,
&Length);
_tcscpy(m_Adapter[adapter_num].driver, pBuffer);
adapter_num++;
}
}
/* GetRegistryProperty是对SetupDiGetDeviceRegistryProperty封装***************/
BOOL GetRegistryProperty(HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
ULONG Property,
LPTSTR* Buffer,
PULONG Length)
{
while (!SetupDiGetDeviceRegistryProperty(
DeviceInfoSet,
DeviceInfoData,
Property,
NULL,
(PBYTE)(*Buffer),
*Length,
Length
))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (*(LPTSTR *)Buffer)
LocalFree(*(LPTSTR *)Buffer);
*Buffer = (LPTSTR)LocalAlloc(LPTR, *Length);
}else {
return FALSE;
}
}
return TRUE;
}
/* m_Adapter的数据结构 */
typedef struct adapter_info_s {
char name[NAME_LEN]; /* 内部设备名, UUID的字符串形式 */
char desc[NAME_LEN]; /* 网卡描述 */
char driver[NAME_LEN]; /* 网卡在注册表中的位置, 如{4D36E972-E325-11CE-BFC1-08002BE10318}\0011
实际完整的键名为System\\CurrentControlSet\\Control\\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0011
该键包含的内容与SetupDiGetDeviceRegistryProperty得到的设备属性基本相同
如NetCfgInstanceId即为内部设备名 DriverDesc为设备描述 */
int index;
}adapter_info_t;
/*****************************************************************************
用何名称区分不同的网卡
有如下名称可供选择
本地连接名, 这是系统使用的方法, 调用的是netman.dll中的未公开函数HrLanConnectionNameFromGuidOrPath(其原型笔者正在调试之中, 成功之后会另行撰文); 其实也可从注册表中获得HKLM\System\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}\Connection\Name
网卡类型描述
设备友好名 它与网卡类型描述基本相同, 当存在同种类型的网卡, 它会加#n(n = 2, 3, 4...)以示区分
如本程序中笔者即以设备友好名区分网卡
*****************************************************************************/
/* 重启网卡的过程************************************************************/
k = pAdapter->GetCurSel(); /* m_Adapter[k]即当前网卡 */
if (SetupDiEnumDeviceInfo(m_hDevInfo, m_Adapter[k].index ,&DeviceInfoData))
{
hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_DISABLE); /* 禁用网卡 */
ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_ENABLE); /* 启用网卡 */
/* 重启网卡, 一般情况下, 以下命令相当于前两命令的组合. 但我仍建议使用前者 */
// ChangeDeviceState(m_hDevInfo, &DeviceInfoData, DICS_PROPCHANGE);
SetCursor(hCursor);
}
/* 扫尾工作 */
SetupDiDestroyDeviceInfoList(m_hDevInfo);
总结: 通过网卡重启更改IP的方法有两个步骤: 修改注册表, 重启网卡. 重启网卡的全过程上面已作描述. 注册表修改的内容为文中列出四个主要项, 如{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}的网卡名称即是内部设备名, 在adapter结构中已给出. 整个注册表修改的过程比较简单, 本文不加叙述.
方法二:未公开函数
Windows系统中, 更改Windows网卡属性选项中IP地址, 可以即时使更改生效, 并且没有重启网卡的过程. 系统自带的netsh也能通过命令行或脚本文件的形式, 完成更改IP的功能时, 也不需要重启网卡
同时也有很多共享软件, 可以实现同样的功能, 常见IP地址更改软件有IPFreeSet, IPChanger, IPProfile, IPHelp, IPSet, SNet等.
笔者通过分析netsh发现一个未公开函数, 即用netcfgx.dll封装的dhcpcsvc.dll中DhcpNotifyConfigChange函数
具体的方法参见VCKB 25期 王骏先生的 "不重起Windows直接更改IP地址", 他得到的函数原型比我准确, 思路也很清晰.
分析上述共享软件时, 发现其技术要点不外乎三种: 使用未公开函数, 调用netsh命令, 重启网卡硬件. 调用netsh命令的实质还是使用未公开函数
使用未公开函数的有: IPFreeSet, IPChanger
调用netsh命令的有 : IPHelp, IPSet. 两者都是用Delphi开发的.
重启网卡硬件: IPSwitcher
速度比较: 因为netsh本身的实现是调用netcfgx.dll, netcfgx.dll封装了对未公开函数的使用, 故效率相对较低. 在一台CPU:PIII500/RAM:256/XP的系统中, IPHelp需要6~7秒才能完成, 而IPFreeSet只需要1~2秒.
方法三:一卡多IP
除以上两个方法外, 笔者再介绍一种方法. 无论是在Windows下还是在Linux下, 一块网卡都可同时具有多个IP地址. 根据TCP/IP原理, 在网络层标识通信节点是IP地址, 在链路层上的则是MAC地址. 只要通过ARP, 将多个IP与一个MAC对应起来, 就可实现一网卡多IP(其实是一MAC多IP). 系统本身也有相应的设置选项, 如windows是通过TCP/IP属性的高级选项添加的, Linux下可由ifconfig命令添加.
iphlpapi提供AddIPAddress和DelIPAddress. 如果能先加入新的IP, 再去除原来的IP, 即可实现IP地址的更改.
具体内容参见我下篇文章"iphlpapi"的使用
————————————————
版权声明:本文为CSDN博主「笨笨D幸福」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/bbdxf/article/details/7548443
在程序中修改IP win7 winXP(参考1)的更多相关文章
- windows中修改IP映射的位置
windows中修改IP映射的位置 置顶 2018年08月05日 14:42:44 wangxiaolong0 阅读数:1473 在安装linux之后,发现windows不能通过映射来访问linu ...
- 如何在Ubuntu server中修改IP
详细请移步至博客https://blog.csdn.net/shenzhen_zsw/article/details/74025066 方法一. sudo ifconfig eth0 100.100 ...
- 在Linux系统中修改IP地址
在Linux系统中,通过编辑网络配置文件,设置系统IP地址,当然要在root权限下执行,具体步骤如下: 1.切换路径到/etc/sysconfig/network-scripts [root@Comp ...
- 在小程序中修改上一个页面里data中的数据调用上一个页面的方法
//获取已经打开的页面的数组 var pages = getCurrentPages(); //获取上一个页面的所有的方法和data中的数据 var lastpage = pages[pages.l ...
- C程序之修改Windows的控制台颜色(转载)
Windows的CMD可以和Linux下的终端一样可以有五颜六色,目前我在网上找到2种方法可以修改Windows的CMD,当然都是在代码中修改的.在“CMD”->“属性”->“颜色”,这种 ...
- Linux命令行修改IP、网关、DNS的方法
Linux中在命令行中修改IP地址.网关.DNS的方法. 网卡eth0 IP修改为 102.168.0.1 复制代码代码如下: ifconfig eth0 102.168.0.1 netmask ...
- Ubuntu16.04修改IP及时生效
1.Network Connetions 窗口管理器中修改IP 2.ifconfig查看网卡名字 3.刷新IP sudo ip addr flush enp2s0 4.sudo service net ...
- 如何限制修改IP地址;如何禁止显示的本地连接属性
现在很多单位都配置了局域网,为了便于进行网络管理,同时为了提高的登录网络的速度,网管人员一般都为局域网中的每台电脑都指定了IP地址.但是在windows环境下其他用户很容易修改IP地址配置,这样就很容 ...
- 开发H5程序或者小程序的时候,后端Web API项目在IISExpress调试中使用IP地址,便于开发调试
在我们开发开发H5程序或者小程序的时候,有时候需要基于内置浏览器或者微信开发者工具进行测试,这个时候可以采用默认的localhost进行访问后端接口,一般来说没什么问题,如果我们需要通过USB基座方式 ...
随机推荐
- Java连载1-概述&常用的dos命令
本想写完那两个再开始新的,然而客观条件不允许,之前从未接触过Java,从零开始吧!!! 一.概述 C盘下:programme file 一般为64位程序安装的目录,programme file(X ...
- Python连载17-排序函数&返回函数的函数
一.高阶函数-排序 1.定义:把一个序列按照给定算法进行排序 2.key:在排序前对每一个元素进行key函数运算,可以理解成按照key函数定义的逻辑进行排序 3.python2和python3相差巨大 ...
- antd模块组件文档思维导图整理
- 快速认识springcloud微服务
这周浅显的学习了springcloud.简单聊一下微服务.所谓的微服务远远没有我想想的那么高端难以理解,简单说,就是多个服务分布在不同的服务器上,由这些服务互相配合完成某一项任务.那服务和服务之间调用 ...
- 快速缓存刷新CDN节点的方法
缓存刷新方式有 URL 刷新.目录刷新和 URL 预热.URL 刷新是以文件为单位进行缓存刷新.目录刷新是以目录为单位,将目录下的所有文件进行缓存刷新.URL 预热是以文件为单位进行资源预热. 刷新后 ...
- docker入门与部署微服务--学习笔记
最近公司进一步去windows,走向 linux+云化. 原来的一大坨windows虚拟机服务器都要转向linux, 既然走向linux的话,那么docker肯定是要涉足的. 故学习了docker入门 ...
- redis 阻塞原因
1.内因: A.api或数据结构使用不合理: 如:对一个包含上万元素的hash结构执行hgetall操作,数据量大且命令复杂度O(n),必然阻塞 B.慢查询:前面有介绍 C.大对象: 执行./redi ...
- Expression Tree上手指南 (一)【转】
大家可能都知道Expression Tree是.NET 3.5引入的新增功能.不少朋友们已经听说过这一特性,但还没来得及了解.看看博客园里的老赵等诸多牛人,将Expression Tree玩得眼花缭乱 ...
- Elasticsearch 使用 php curl 插入数据
<?php /** * Created by PhpStorm. * User: func7 * Date: 2018/11/8 * Time: 11:24 */ set_time_limit( ...
- Eureka源码解析系列文章汇总
先看一张图 0 这个图是Eureka官方提供的架构图,整张图基本上把整个Eureka的核心功能给列出来了,当你要阅读Eureka的源码时可以参考着这个图和下方这些文章 EurekaServer Eur ...