Potrzebuję sposobu, aby uzyskać adres MAC maszyny niezależnie od systemu operacyjnego, na którym działa, przy użyciu C #. Aplikacja będzie musiała działać na XP / Vista / Win7 32 i 64 bit, a także na tych systemach operacyjnych, ale z domyślnym językiem obcym. Wiele poleceń C # i zapytań systemu operacyjnego nie działa w różnych systemach operacyjnych. Jakieś pomysły? Skrobałem wynik polecenia „ipconfig / all”, ale jest to strasznie zawodne, ponieważ format wyjściowy różni się na każdym komputerze.
Dzięki
Odpowiedzi:
Czystsze rozwiązanie
var macAddr = ( from nic in NetworkInterface.GetAllNetworkInterfaces() where nic.OperationalStatus == OperationalStatus.Up select nic.GetPhysicalAddress().ToString() ).FirstOrDefault();
Lub:
źródło
return NetworkInterface.GetAllNetworkInterfaces().Where(nic => nic.OperationalStatus == OperationalStatus.Up).Select(nic => nic.GetPhysicalAddress().ToString()).FirstOrDefault();
(Jeśli to nie jest twoja sprawa, powinna być twoja.)var 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();
FirstOrDefault
przed finałemSelect
. W ten sposób otrzyma adres fizyczny i serializuje go tylko dla tegoNetworkInterface
, co otrzymujesz. Nie zapomnij dodać znaku zerowego (?) PoFirstOrDefault
.NetworkInterface .GetAllNetworkInterfaces() .FirstOrDefault(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)? .GetPhysicalAddress().ToString();
Oto kod w języku C #, który zwraca adres MAC pierwszego działającego interfejsu sieciowego. Zakładając, że
NetworkInterface
zestaw jest zaimplementowany w środowisku uruchomieniowym (tj. Mono) używanym w innych systemach operacyjnych, to działałoby w innych systemach operacyjnych.Nowa wersja: zwraca kartę sieciową z największą szybkością, która ma również prawidłowy adres MAC.
/// <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; }
Wersja oryginalna: po prostu zwraca pierwszą.
/// <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; }
Jedyne, co mi się nie podoba w tym podejściu, to to, że jeśli masz np. Nortel Packet Miniport lub jakiś rodzaj połączenia VPN, może on zostać wybrany. O ile wiem, nie ma sposobu, aby odróżnić adres MAC rzeczywistego urządzenia fizycznego od pewnego typu interfejsu sieci wirtualnej.
źródło
using System.Net.NetworkInformation;
Adres_MAC własność klasy Win32_NetworkAdapterConfiguration WMI może dostarczyć adres MAC adaptera jest. (Przestrzeń nazw 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"
Jeśli nie znasz interfejsu WMI API (Windows Management Instrumentation), tutaj znajdziesz dobry przegląd aplikacji .NET.
Usługa WMI jest dostępna we wszystkich wersjach systemu Windows z uruchomieniem .Net.
Oto przykład kodu:
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()); } }
źródło
WMI to najlepsze rozwiązanie, jeśli komputer, z którym się łączysz, to komputer z systemem Windows, ale jeśli patrzysz na linuksa, mac lub inny typ karty sieciowej, będziesz musiał użyć czegoś innego. Oto kilka opcji:
Oto próbka punktu 3. To wydaje się być najlepszą opcją, jeśli WMI nie jest opłacalnym rozwiązaniem:
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); }
Aby udzielić kredytu tam, gdzie jest to należne, oto podstawa dla tego kodu: http://www.pinvoke.net/default.aspx/iphlpapi.sendarp#
źródło
Używamy WMI, aby uzyskać adres mac interfejsu z najniższą metryką, np. Okna interfejsu będą wolały używać, na przykład:
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; }
Lub w Silverlight (wymaga podwyższonego zaufania):
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; }
źródło
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; }
źródło
IMHO zwracający pierwszy adres mac nie jest dobrym pomysłem, zwłaszcza gdy hostowane są maszyny wirtualne. Dlatego sprawdzam sumę wysłanych / odebranych bajtów i wybieram najczęściej używane połączenie, które nie jest idealne, ale powinno być poprawne 9/10 razy.
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; }
źródło
Ta metoda określi adres MAC interfejsu sieciowego używanego do połączenia z określonym adresem URL i portem.
Wszystkie odpowiedzi tutaj nie są w stanie osiągnąć tego celu.
Napisałem tę odpowiedź lata temu (w 2014 roku). Postanowiłem więc trochę „lifting twarzy”. Proszę spojrzeć na sekcję aktualizacji
/// <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; }
Aby to nazwać, musisz podać adres URL, aby połączyć się w ten sposób:
var mac = GetCurrentMAC("www.google.com");
Możesz również określić numer portu. Jeśli nie zostanie określony, wartość domyślna to 80.
AKTUALIZACJE:
2020
źródło
Możesz wybrać identyfikator karty sieciowej:
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.OperationalStatus == OperationalStatus.Up){ if (nic.Id == "yay!") } }
To nie jest adres MAC, ale jest to unikalny identyfikator, jeśli tego właśnie szukasz.
źródło
Naprawdę podoba mi się rozwiązanie AVee z najniższą metryką połączenia IP! Ale jeśli zainstalowana zostanie druga nisza z tą samą metryką, porównanie MAC może się nie udać ...
Lepiej zapisz opis interfejsu z MAC. W późniejszych porównaniach możesz zidentyfikować właściwe nic na podstawie tego ciągu. Oto przykładowy kod:
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; }
źródło
powiedzmy, że mam połączenie TcpConnection przy użyciu mojego lokalnego adresu IP 192.168.0.182. Jeśli zechcę poznać adres MAC tej karty sieciowej, zadzwonię do meothodu jako:
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; }
źródło
Naprawdę nie znoszę odkopać tego starego posta, ale czuję, że pytanie zasługuje na inną odpowiedź dotyczącą systemu Windows 8-10.
Korzystając z NetworkInformation z obszaru nazw Windows.Networking.Connectivity , można uzyskać identyfikator używanej przez system Windows karty sieciowej. Następnie możesz uzyskać adres MAC interfejsu ze wspomnianej wcześniej GetAllNetworkInterfaces ().
Nie będzie to działać w aplikacjach ze Sklepu Windows, ponieważ NetworkInterface w System.Net.NetworkInformation nie ujawnia 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; }
źródło
string mac = ""; foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.OperationalStatus == OperationalStatus.Up && (!nic.Description.Contains("Virtual") && !nic.Description.Contains("Pseudo"))) { if (nic.GetPhysicalAddress().ToString() != "") { mac = nic.GetPhysicalAddress().ToString(); } } } MessageBox.Show(mac);
źródło
Zmieniono nieco blak3r jego kod. Jeśli masz dwa adaptery o tej samej prędkości. Sortuj według MAC, aby zawsze uzyskać tę samą wartość.
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; }
źródło
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.OperationalStatus == OperationalStatus.Up) { PhysicalAddress Mac = nic.GetPhysicalAddress(); } }
źródło
ipconfig.exe
jest implementowany przy użyciu różnych bibliotek DLL, w tymiphlpapi.dll
... Wyszukiwanie w wyszukiwarceiphlpapi
ujawnia odpowiednie API Win32 udokumentowane w MSDN.źródło
Spróbuj tego:
/// <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; }
źródło