/*?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} 011?? ????实际完整的键名为SystemCurrentControlSetControlClass{4D36E972-E325-11CE-BFC1-08002BE10318} 011?? ????该键包含的内容与SetupDiGetDeviceRegistryProperty得到的设备属性基本相同? ????如NetCfgInstanceId即为内部设备名?DriverDesc为设备描述????*/? ????int?index;? }adapter_info_t;? ?????
/*****************************************************************************? ?用何名称区分不同的网卡? ?有如下名称可供选择? ????本地连接名,?这是系统使用的方法,?调用的是netman.dll中的未公开函数HrLanConnectionNameFromGuidOrPath(其原型笔者正在调试之中,?成功之后会另行撰文); 其实也可从注册表中获得HKLMSystemCurrentControlSetControlNetwork{4D36E972-E325-11CE-BFC1-08002BE10318}{97EFDAD8-EB2D-4F40-9B07-0FCD706FCB6D}ConnectionName? ????网卡类型描述? ????设备友好名????????它与网卡类型描述基本相同,?当存在同种类型的网卡,?它会加#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,?DICS_ENABLE);????/*?启用网卡?*/????????? ????????/*?重启网卡,?一般情况下,?以下命令相当于前两命令的组合.?但我仍建议使用前者?*/????? ????????//????ChangeDeviceState(m_hDevInfo,?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
(编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|