| /*?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
 (编辑:宣城站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |