machine - networkinterface c#
Método confiable para obtener la dirección MAC de la máquina en C# (14)
Necesito una forma de obtener la dirección MAC de una máquina, independientemente del SO que esté ejecutando con C #. La aplicación deberá funcionar en XP / Vista / Win7 de 32 y 64 bits, así como en esos sistemas operativos, pero con un idioma extranjero predeterminado. Muchos de los comandos C # y consultas de OS no funcionan en todo el sistema operativo. ¿Algunas ideas? He estado raspando la salida de "ipconfig / all", pero esto es terriblemente poco confiable ya que el formato de salida difiere en cada máquina.
Gracias
¡Realmente me gusta la solución de AVee con la métrica de conexión IP más baja! Pero si se instala una segunda nic con la misma métrica, la comparación MAC podría fallar ...
Es mejor que almacene la descripción de la interfaz con el MAC. En comparaciones posteriores, puede identificar el nic correcto con esta cadena. Aquí hay un código de muestra:
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;
}
Aquí hay un código C # que devuelve la dirección MAC de la primera interfaz de red operativa. Suponiendo que el ensamblado NetworkInterface
se implementa en el tiempo de ejecución (es decir, Mono) utilizado en otros sistemas operativos, esto funcionaría en otros sistemas operativos.
Nueva versión: devuelve la NIC con la velocidad más rápida que también tiene una dirección MAC válida.
/// <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;
}
Versión original: simplemente devuelve el primero.
/// <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;
}
Lo único que no me gusta de este enfoque es que si tiene un minipuerto de paquete de Nortel o algún tipo de conexión VPN, tiene la posibilidad de ser elegido. Por lo que puedo decir, no hay forma de distinguir el MAC de un dispositivo físico real de algún tipo de interfaz de red virtual.
Cambié un poco el código de Blak3r. En caso de que tengas dos adaptadores con la misma velocidad. Ordene por MAC, para que siempre obtenga el mismo valor.
public string GetMacAddress()
{
const int MIN_MAC_ADDR_LENGTH = 12;
string macAddress = string.Empty;
Dictionary<string, long> macPlusSpeed = new Dictionary<string, long>();
try
{
foreach(NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
System.Diagnostics.Debug.WriteLine("Found MAC Address: " + nic.GetPhysicalAddress() + " Type: " + nic.NetworkInterfaceType);
string tempMac = nic.GetPhysicalAddress().ToString();
if(!string.IsNullOrEmpty(tempMac) && tempMac.Length >= MIN_MAC_ADDR_LENGTH)
macPlusSpeed.Add(tempMac, nic.Speed);
}
macAddress = macPlusSpeed.OrderByDescending(row => row.Value).ThenBy(row => row.Key).FirstOrDefault().Key;
}
catch{}
System.Diagnostics.Debug.WriteLine("Fastest MAC address: " + macAddress);
return macAddress;
}
La propiedad MACAddress de la clase WMI Win32_NetworkAdapterConfiguration puede proporcionarle la dirección MAC de un adaptador. (Espacio de nombres de gestión del sistema)
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"
Si no está familiarizado con la API WMI (Instrumentación de administración de Windows), aquí hay una buena descripción general de las aplicaciones .NET.
WMI está disponible en todas las versiones de Windows con .Net runtime.
Aquí hay un ejemplo de código:
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());
}
}
Necesitaba obtener el MAC para que se utilizara la NIC real para conectarse a Internet; para determinar qué interfaz usaba WCF en mi aplicación cliente.
Veo muchas respuestas aquí, pero ninguna que me haya ayudado. Espero que esta respuesta ayude a alguien.
Esta solución devuelve el MAC de la NIC que se utiliza para conectarse a Internet.
private static PhysicalAddress GetCurrentMAC(string allowedURL)
{
TcpClient client = new TcpClient();
client.Client.Connect(new IPEndPoint(Dns.GetHostAddresses(allowedURL)[0], 80));
while(!client.Connected)
{
Thread.Sleep(500);
}
IPAddress address2 = ((IPEndPoint)client.Client.LocalEndPoint).Address;
client.Client.Disconnect(false);
NetworkInterface[] allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
client.Close();
if(allNetworkInterfaces.Length > 0)
{
foreach(NetworkInterface interface2 in allNetworkInterfaces)
{
UnicastIPAddressInformationCollection unicastAddresses = interface2.GetIPProperties().UnicastAddresses;
if((unicastAddresses != null) && (unicastAddresses.Count > 0))
{
for(int i = 0; i < unicastAddresses.Count; i++)
if(unicastAddresses[i].Address.Equals(address2))
return interface2.GetPhysicalAddress();
}
}
}
return null;
}
Para llamarlo necesitas pasar una URL para conectarte así:
PhysicalAddress mac = GetCurrentMAC("www.google.com");
Podrías buscar la ID de NIC:
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) {
if (nic.OperationalStatus == OperationalStatus.Up){
if (nic.Id == "yay!")
}
}
No es la dirección MAC, pero es un identificador único, si eso es lo que estás buscando.
Prueba esto:
/// <summary>
/// returns the first MAC address from where is executed
/// </summary>
/// <param name="flagUpOnly">if sets returns only the nic on Up status</param>
/// <returns></returns>
public static string[] getOperationalMacAddresses(Boolean flagUpOnly)
{
string[] macAddresses = new string[NetworkInterface.GetAllNetworkInterfaces().Count()];
int i = 0;
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus == OperationalStatus.Up || !flagUpOnly)
{
macAddresses[i] += ByteToHex(nic.GetPhysicalAddress().GetAddressBytes());
//break;
i++;
}
}
return macAddresses;
}
Realmente odio desenterrar esta publicación anterior, pero creo que la pregunta merece otra respuesta específica para Windows 8-10.
Con NetworkInformation desde el espacio de nombres de Windows.Networking.Connectivity , puede obtener el id de las ventanas del adaptador de red. Luego puede obtener la dirección MAC de la interfaz de los GetAllNetworkInterfaces () mencionados anteriormente.
Esto no funcionará en las aplicaciones de la Tienda Windows ya que NetworkInterface en System.Net.NetworkInformation no expone GetAllNetworkInterfaces.
string GetMacAddress()
{
var connectionProfile = NetworkInformation.GetInternetConnectionProfile();
if (connectionProfile == null) return "";
var inUseId = connectionProfile.NetworkAdapter.NetworkAdapterId.ToString("B").ToUpperInvariant();
if(string.IsNullOrWhiteSpace(inUseId)) return "";
var mac = NetworkInterface.GetAllNetworkInterfaces()
.Where(n => inUseId == n.Id)
.Select(n => n.GetPhysicalAddress().GetAddressBytes().Select(b=>b.ToString("X2")))
.Select(macBytes => string.Join(" ", macBytes))
.FirstOrDefault();
return mac;
}
Solución más limpia
var macAddr =
(
from nic in NetworkInterface.GetAllNetworkInterfaces()
where nic.OperationalStatus == OperationalStatus.Up
select nic.GetPhysicalAddress().ToString()
).FirstOrDefault();
O:
String firstMacAddress = NetworkInterface
.GetAllNetworkInterfaces()
.Where( nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback )
.Select( nic => nic.GetPhysicalAddress().ToString() )
.FirstOrDefault();
Usamos WMI para obtener la dirección MAC de la interfaz con la métrica más baja, por ejemplo, las ventanas de interfaz preferirán usar, como esta:
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;
}
O en Silverlight (necesita una confianza elevada):
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;
}
WMI es la mejor solución si la máquina a la que se está conectando es una máquina de Windows, pero si está mirando un linux, mac u otro tipo de adaptador de red, necesitará usar algo más. Aquí hay algunas opciones:
- Use el comando DOS nbtstat -a. Crea un proceso, llama a este comando, analiza el resultado.
- Primero haga ping a la IP para asegurarse de que su NIC almacena en caché el comando en su tabla ARP, luego use el comando de DOS arp -a. Analice el resultado del proceso como en la opción 1.
- Utilice una temida llamada no gestionada a sendarp en el iphlpapi.dll
Aquí hay una muestra del artículo n. ° 3. Esta parece ser la mejor opción si WMI no es una solución viable:
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);
}
Para dar crédito donde es debido, esta es la base de ese código: http://www.pinvoke.net/default.aspx/iphlpapi.sendarp#
digamos que tengo un TcpConnection usando mi ip local de 192.168.0.182. Entonces, si me gustaría saber la dirección MAC de esa NIC, llamaré al meothod como: GetMacAddressUsedByIp("192.168.0.182")
public static string GetMacAddressUsedByIp(string ipAddress)
{
var ips = new List<string>();
string output;
try
{
// Start the child process.
Process p = new Process();
// Redirect the output stream of the child process.
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = "ipconfig";
p.StartInfo.Arguments = "/all";
p.Start();
// Do not wait for the child process to exit before
// reading to the end of its redirected stream.
// p.WaitForExit();
// Read the output stream first and then wait.
output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
}
catch
{
return null;
}
// pattern to get all connections
var pattern = @"(?xis)
(?<Header>
(/r|/n) [^/r]+ : /r/n/r/n
)
(?<content>
.+? (?= ( (/r/n/r/n)|($)) )
)";
List<Match> matches = new List<Match>();
foreach (Match m in Regex.Matches(output, pattern))
matches.Add(m);
var connection = matches.Select(m => new
{
containsIp = m.Value.Contains(ipAddress),
containsPhysicalAddress = Regex.Match(m.Value, @"(?ix)Physical /s Address").Success,
content = m.Value
}).Where(x => x.containsIp && x.containsPhysicalAddress)
.Select(m => Regex.Match(m.content, @"(?ix) Physical /s address [^:]+ : /s* (?<Mac>[^/s]+)").Groups["Mac"].Value).FirstOrDefault();
return connection;
}
ipconfig.exe
se implementa utilizando varias DLL incluyendo iphlpapi.dll
... Google buscando iphlpapi
revela una API de Win32 correspondiente documentada en MSDN.
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;
}