网卡及MAC地址列表
修改网卡MAC地址首先要获取系统中网卡列表及对应的MAC地址,大至有以下几种方法:
1、WMI的Win32_NetworkAdapter和Win32_Win32_NetworkAdapterConfiguration类
SELECT Name, MACAddress FROM Win32_NetworkAdapter WHERE AdapterTypeID = 0
SELECT Name, MACAddress FROM Win32_NetworkAdapter WHERE IPEnabled = true
2、Win32API:GetAdapterInfo、NetBios或SNMP等API函数
GetAdapterInfo和NetBios的相关代码可以参考PInvoke.net
3、COM组件hnetcfg.dll
引用COM组件NetCon 1.0 Type Library或引用DLL %System32%/hnetcfg.dll 并using NETCONLib;
NetSharingManager nsm = new NetSharingManager(); INetSharingEveryConnectionCollection insecc = nsm.EnumEveryConnection; foreach (INetConnection inc in insecc) { INetConnectionProps incp = nsm.get_NetConnectionProps(inc); if (incp.MediaType == tagNETCON_MEDIATYPE.NCM_LAN) { Trace.WriteLine(incp.Name + "/" + incp.DeviceName); } }
注意:通过NetSharingManager无法直接获取网卡对应的MAC地址
4、通过.net类System.Net.NetworkInformation;
NetworkInterface[] nis = NetworkInterface.GetAllNetworkInterfaces(); foreach (NetworkInterface ni in nis) { if (ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet) { Trace.WriteLine(ni.Name + "/" + ni.Description + ":" + ni.GetPhysicalAddress()); } }
此外还可以通过
访问注册表项HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{4D36E972-E325-11CE-BFC1-08002bE10318}、应用Shell32.dll的NameSpace(3)、调用netsh、netstat 等命令行工具并分析输出等等一些方法来枚举网卡信息
MAC地址修改
MAC地址是写在网卡固件里的,但Windows会把MAC地址保存在注册表中,在应用请求MAC地址时,优先返回注册表中的值,而不是固件中的地址。
在注册表位置“HKEY_LOCAL_MACHINE/System/Current ControlSet/Services/Class/Net”,会看到类似“0000”、“0001”、“0002”的子键。从“0000”子键开始点击,依次查找子键下的“DriverDesc”键的内容,直到找到与我们查找的目标完全相同的网卡注册表信息为止。当找到正确的网卡后,在相应的键下新建一个名称为“NetWorkAddress”的字符串,值为新的MAC地址,新的MAC地址应该是一个12位的十六进制数字或字母,其间没有“-”,类似“000000000000”的这样的数值。
其它一些MAC地址修改的方法请参考相关文档
重启网卡
通过注册表修改MAC地址后,需要重启网卡才通使修改生效,大至有以下几种方法可以实现硬件设备的禁和启用
1、WMI
WMI的Win32_NetworkAdapter提供了Reset、Disable和Enable方法,不过对操作系统版本有要求,XP中调用会触发异常:“没有任何类别中执行这个方法”
2、 netsh
这是一个windows自带的命令行工具,“netsh interface show interface” 用于显示网络接口信息,“netsh interface set interface name="本地连接" disabled或enabled” 可用于禁止网卡,但这个调用也对OS版本有限制,XP中无法成功
3、DevCon
devcon也是一个Microsfot提供的命令行工具,需要到MS的网站下载,MS对它的描述是:
DevCon 实用工具是一种命令行实用工具,可以替代设备管理器。使用 DevCon,您可以启用、禁用、重新启动、更新、删除和查询单个设备或一组设备。DevCon 还提供与驱动程序开发人员有关、但无法在设备管理器中看到的信息。
该命令行工具的使用请参考相关文档
4、COM组件hnetcfg.dll
NETCONLib的INetConnection提供了Disconnect()和Connect()方法
NetSharingManager nsm = new NetSharingManager(); INetSharingEveryConnectionCollection insecc = nsm.EnumEveryConnection; foreach (INetConnection inc in insecc) { INetConnectionProps incp = nsm.get_NetConnectionProps(inc); if (incp.MediaType == tagNETCON_MEDIATYPE.NCM_LAN) { if (incp.DeviceName == "Realtek RTL8139/810x Family Fast Ethernet NIC") { inc.Disconnect(); inc.Connect(); //在这种情况下对Status的输出是NCS_CONNECTED,这并不准确,因为Connect()是异步的 Trace.WriteLine(incp.Status); } } }
重启确认
上述重启网卡的方法,无论是命令行还是编程方式,都存在一个不同步的问题
即先ping ip -t 然后在一个新的进程中用某一方法禁止然后启用网卡,在调用返回后的一段时间内,ping 仍然是不可达的
在。
而在编程方式下可以利用“网卡及MAC地址列表”中描述的四中方法都有的一个特性,就是不能枚举被禁用的网卡,也就是说可以利用枚举出来的网卡中是否包含指定网卡,来达到检测是否启用完毕的目的。
开启ping,用devcon和INetConnection重启网卡,并用以上述四种方法枚举网卡,WMI和INetConnectionProps的表现基本一致,即重启之后没有ping通之前就能枚举到网卡,且相应的NetConnectionStatus和Status属性均为已连接,而GetApapterInfo和System.Net.NetworkInformation方式较为准确,ping通之后才枚举到网卡,且NetworkInfomation的OperationalStatus属性为up,GetApaterInfo中没有连接状态相关的属性。
想要枚举到被禁用的网卡请使用setupapi,获取网卡固件中的MAC地址请使用DeviceIoConstrol API,这是两个让人头痛的应用,具体说明请参考相关文档
参考资料:
多种方法修改网卡MAC物理地址
http://tech.sina.com.cn/s/2006-07-26/09431055778.shtml
DevCon 命令行实用工具可替代设备管理器
http://support.microsoft.com/kb/311272/zh-cn
微软DevCon 工具 可以命令行禁用或启用网卡-附两个小批处理!
http://www.cnblogs.com/HeroBeast/archive/2008/10/30/1322675.html
Mac地址自动生成器核心处理类
http://blog.csdn.net/arden27336/archive/2008/12/15/3523203.aspx
C#实现启用、禁用本地网络的三种方式
http://blog.csdn.net/zjfei/archive/2009/04/23/4104660.aspx
C#实现启用或停用本地网络连接
http://blog.51haipai.com/article.asp?id=24