我需要一种使用C#获取机器的MAC地址的方法,不考虑它正在运行的操作系统。
该应用程序将需要在XP / Vista / Win7 32位和64位上运行,并且还需要在这些操作系统上但默认语言是外语的情况下工作。另外,许多C#命令和操作系统查询在所有操作系统上都无法正常工作。
您有任何想法吗?
我一直在爬取ipconfig /all
的输出,但这非常不可靠,因为输出格式在每台计算机上都不同。
我需要一种使用C#获取机器的MAC地址的方法,不考虑它正在运行的操作系统。
该应用程序将需要在XP / Vista / Win7 32位和64位上运行,并且还需要在这些操作系统上但默认语言是外语的情况下工作。另外,许多C#命令和操作系统查询在所有操作系统上都无法正常工作。
您有任何想法吗?
我一直在爬取ipconfig /all
的输出,但这非常不可靠,因为输出格式在每台计算机上都不同。
更简洁的解决方案
var macAddr =
(
from nic in NetworkInterface.GetAllNetworkInterfaces()
where nic.OperationalStatus == OperationalStatus.Up
select nic.GetPhysicalAddress().ToString()
).FirstOrDefault();
或者:String firstMacAddress = NetworkInterface
.GetAllNetworkInterfaces()
.Where( nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback )
.Select( nic => nic.GetPhysicalAddress().ToString() )
.FirstOrDefault();
return NetworkInterface.GetAllNetworkInterfaces().Where(nic => nic.OperationalStatus == OperationalStatus.Up).Select(nic => nic.GetPhysicalAddress().ToString()).FirstOrDefault();
(如果这不是你喜欢的东西,那么它应该成为你喜欢的东西。) - GONealevar networks = NetworkInterface.GetAllNetworkInterfaces();
var activeNetworks = networks.Where(ni => ni.OperationalStatus == OperationalStatus.Up && ni.NetworkInterfaceType != NetworkInterfaceType.Loopback);
var sortedNetworks = activeNetworks.OrderByDescending(ni => ni.Speed);
return sortedNetworks.First().GetPhysicalAddress().ToString();
- Graham LaightSelect
之前,您可以调用 FirstOrDefault
。这样,它只会获取物理地址并将其序列化为实际获取的 NetworkInterface
。不要忘记在 FirstOrDefault
后添加空值检查(?)。 - GregorMohorkoNetworkInterface .GetAllNetworkInterfaces() .FirstOrDefault(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)? .GetPhysicalAddress().ToString();
- Alessandro Muzzi这里有一些C#代码,可以返回第一个正在运行的网络接口的MAC地址。假设在其他操作系统上使用的运行时(例如Mono)中实现了NetworkInterface
程序集,则此代码也可用于其他操作系统。
新版本:返回速度最快且具有有效MAC地址的NIC。
/// <summary>
/// Finds the MAC address of the NIC with maximum speed.
/// </summary>
/// <returns>The MAC address.</returns>
private string GetMacAddress()
{
const int MIN_MAC_ADDR_LENGTH = 12;
string macAddress = string.Empty;
long maxSpeed = -1;
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
log.Debug(
"Found MAC Address: " + nic.GetPhysicalAddress() +
" Type: " + nic.NetworkInterfaceType);
string tempMac = nic.GetPhysicalAddress().ToString();
if (nic.Speed > maxSpeed &&
!string.IsNullOrEmpty(tempMac) &&
tempMac.Length >= MIN_MAC_ADDR_LENGTH)
{
log.Debug("New Max Speed = " + nic.Speed + ", MAC: " + tempMac);
maxSpeed = nic.Speed;
macAddress = tempMac;
}
}
return macAddress;
}
翻译版本:只返回第一个。
/// <summary>
/// Finds the MAC address of the first operation NIC found.
/// </summary>
/// <returns>The MAC address.</returns>
private string GetMacAddress()
{
string macAddresses = string.Empty;
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus == OperationalStatus.Up)
{
macAddresses += nic.GetPhysicalAddress().ToString();
break;
}
}
return macAddresses;
}
我不喜欢这种方法的唯一问题是,如果你有像Nortel Packet Miniport或某种类型的VPN连接,它有可能被选择。就我所知,没有办法区分实际物理设备的MAC地址和某种虚拟网络接口。
using System.Net.NetworkInformation;
访问NetworkInterface类。 - iancoleman依我之见,返回第一个 MAC 地址并不是一个好主意,特别是当虚拟机被托管时。因此,我会检查发送/接收字节的总和,然后选择使用最多的连接。这并不完美,但应该正确 9/10 次。
public string GetDefaultMacAddress()
{
Dictionary<string, long> macAddresses = new Dictionary<string, long>();
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus == OperationalStatus.Up)
macAddresses[nic.GetPhysicalAddress().ToString()] = nic.GetIPStatistics().BytesSent + nic.GetIPStatistics().BytesReceived;
}
long maxValue = 0;
string mac = "";
foreach(KeyValuePair<string, long> pair in macAddresses)
{
if (pair.Value > maxValue)
{
mac = pair.Key;
maxValue = pair.Value;
}
}
return mac;
}
public static NetworkInterface? GetDefaultMacAddress() => NetworkInterface.GetAllNetworkInterfaces().Where(i => i.OperationalStatus == OperationalStatus.Up).OrderByDescending(i => i.GetIPStatistics().BytesReceived + .GetIPStatistics().BytesSent).FirstOrDefault();
- Simon MourierMACAddress 属性是 Win32_NetworkAdapterConfiguration WMI 类 中的一个属性,可提供适配器的 MAC 地址。(System.Management 命名空间)
MACAddress
Data type: string
Access type: Read-only
Media Access Control (MAC) address of the network adapter. A MAC address is assigned by the manufacturer to uniquely identify the network adapter.
Example: "00:80:C7:8F:6C:96"
如果您不熟悉WMI API(Windows管理工具),这里有一个很好的.NET应用程序的概述。
WMI可在所有版本的Windows上使用,带有.Net运行时。
以下是一个代码示例:
System.Management.ManagementClass mc = default(System.Management.ManagementClass);
ManagementObject mo = default(ManagementObject);
mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
foreach (var mo in moc) {
if (mo.Item("IPEnabled") == true) {
Adapter.Items.Add("MAC " + mo.Item("MacAddress").ToString());
}
}
如果您正在连接的机器是Windows机器,则WMI是最佳解决方案,但如果您要查看的是Linux、Mac或其他类型的网络适配器,则需要使用其他工具。以下是一些选项:
这里是第三个选项的示例。如果WMI不可行,则这似乎是最佳选择:
using System.Runtime.InteropServices;
...
[DllImport("iphlpapi.dll", ExactSpelling = true)]
public static extern int SendARP(int DestIP, int SrcIP, byte[] pMacAddr, ref uint PhyAddrLen);
...
private string GetMacUsingARP(string IPAddr)
{
IPAddress IP = IPAddress.Parse(IPAddr);
byte[] macAddr = new byte[6];
uint macAddrLen = (uint)macAddr.Length;
if (SendARP((int)IP.Address, 0, macAddr, ref macAddrLen) != 0)
throw new Exception("ARP command failed");
string[] str = new string[(int)macAddrLen];
for (int i = 0; i < macAddrLen; i++)
str[i] = macAddr[i].ToString("x2");
return string.Join(":", str);
}
为了给出应有的赞扬,这段代码的基础是:http://www.pinvoke.net/default.aspx/iphlpapi.sendarp#
这个方法将确定用于连接到指定URL和端口的网络接口的MAC地址。
所有这里的答案都不能实现这个目标。
我几年前写了这个答案(在2014年)。所以我决定给它一个小的“翻新”。请查看更新部分。
/// <summary>
/// Get the MAC of the Netowrk Interface used to connect to the specified url.
/// </summary>
/// <param name="allowedURL">URL to connect to.</param>
/// <param name="port">The port to use. Default is 80.</param>
/// <returns></returns>
private static PhysicalAddress GetCurrentMAC(string allowedURL, int port = 80)
{
//create tcp client
var client = new TcpClient();
//start connection
client.Client.Connect(new IPEndPoint(Dns.GetHostAddresses(allowedURL)[0], port));
//wai while connection is established
while(!client.Connected)
{
Thread.Sleep(500);
}
//get the ip address from the connected endpoint
var ipAddress = ((IPEndPoint)client.Client.LocalEndPoint).Address;
//if the ip is ipv4 mapped to ipv6 then convert to ipv4
if(ipAddress.IsIPv4MappedToIPv6)
ipAddress = ipAddress.MapToIPv4();
Debug.WriteLine(ipAddress);
//disconnect the client and free the socket
client.Client.Disconnect(false);
//this will dispose the client and close the connection if needed
client.Close();
var allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
//return early if no network interfaces found
if(!(allNetworkInterfaces?.Length > 0))
return null;
foreach(var networkInterface in allNetworkInterfaces)
{
//get the unicast address of the network interface
var unicastAddresses = networkInterface.GetIPProperties().UnicastAddresses;
//skip if no unicast address found
if(!(unicastAddresses?.Count > 0))
continue;
//compare the unicast addresses to see
//if any match the ip address used to connect over the network
for(var i = 0; i < unicastAddresses.Count; i++)
{
var unicastAddress = unicastAddresses[i];
//this is unlikely but if it is null just skip
if(unicastAddress.Address == null)
continue;
var ipAddressToCompare = unicastAddress.Address;
Debug.WriteLine(ipAddressToCompare);
//if the ip is ipv4 mapped to ipv6 then convert to ipv4
if(ipAddressToCompare.IsIPv4MappedToIPv6)
ipAddressToCompare = ipAddressToCompare.MapToIPv4();
Debug.WriteLine(ipAddressToCompare);
//skip if the ip does not match
if(!ipAddressToCompare.Equals(ipAddress))
continue;
//return the mac address if the ip matches
return networkInterface.GetPhysicalAddress();
}
}
//not found so return null
return null;
}
要调用它,您需要传递一个连接URL,如下所示:
var mac = GetCurrentMAC("www.google.com");
public static string GetMACAddress()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
string mac = (from o in objects orderby o["IPConnectionMetric"] select o["MACAddress"].ToString()).FirstOrDefault();
return mac;
}
或者在Silverlight中(需要提升的信任):
public static string GetMACAddress()
{
string mac = null;
if ((Application.Current.IsRunningOutOfBrowser) && (Application.Current.HasElevatedPermissions) && (AutomationFactory.IsAvailable))
{
dynamic sWbemLocator = AutomationFactory.CreateObject("WbemScripting.SWBemLocator");
dynamic sWbemServices = sWbemLocator.ConnectServer(".");
sWbemServices.Security_.ImpersonationLevel = 3; //impersonate
string query = "SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true";
dynamic results = sWbemServices.ExecQuery(query);
int mtu = int.MaxValue;
foreach (dynamic result in results)
{
if (result.IPConnectionMetric < mtu)
{
mtu = result.IPConnectionMetric;
mac = result.MACAddress;
}
}
}
return mac;
}
public static PhysicalAddress GetMacAddress()
{
var myInterfaceAddress = NetworkInterface.GetAllNetworkInterfaces()
.Where(n => n.OperationalStatus == OperationalStatus.Up && n.NetworkInterfaceType != NetworkInterfaceType.Loopback)
.OrderByDescending(n => n.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
.Select(n => n.GetPhysicalAddress())
.FirstOrDefault();
return myInterfaceAddress;
}
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) {
if (nic.OperationalStatus == OperationalStatus.Up){
if (nic.Id == "yay!")
}
}
它不是MAC地址,但它是一个唯一的标识符,如果这正是你所寻找的。
public static string GetMacAndDescription()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
string mac = (from o in objects orderby o["IPConnectionMetric"] select o["MACAddress"].ToString()).FirstOrDefault();
string description = (from o in objects orderby o["IPConnectionMetric"] select o["Description"].ToString()).FirstOrDefault();
return mac + ";" + description;
}
public static string GetMacByDescription( string description)
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration where IPEnabled=true");
IEnumerable<ManagementObject> objects = searcher.Get().Cast<ManagementObject>();
string mac = (from o in objects where o["Description"].ToString() == description select o["MACAddress"].ToString()).FirstOrDefault();
return mac;
}