C#を使用して実行しているOSに関係なく、マシンのMACアドレスを取得する方法が必要です。アプリケーションは、XP / Vista / Win7 32および64ビット、およびそれらのOSで動作する必要がありますが、外国語がデフォルトです。C#コマンドとOSクエリの多くは、OS全体で機能しません。何か案は?私は "ipconfig / all"の出力をスクレイピングしてきましたが、出力フォーマットがすべてのマシンで異なるため、これはひどく信頼できません。
ありがとう
C#を使用して実行しているOSに関係なく、マシンのMACアドレスを取得する方法が必要です。アプリケーションは、XP / Vista / Win7 32および64ビット、およびそれらのOSで動作する必要がありますが、外国語がデフォルトです。C#コマンドとOSクエリの多くは、OS全体で機能しません。何か案は?私は "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();
(それがあなたのものではない場合、それはあなたのものでなければなりません。)
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
ファイナルの前に呼び出すことができますSelect
。この方法では、物理アドレスのみを取得し、取得した実際のアドレスに対してシリアル化NetworkInterface
します。の後にnullチェック(?)を追加することを忘れないでくださいFirstOrDefault
。
NetworkInterface .GetAllNetworkInterfaces() .FirstOrDefault(nic => nic.OperationalStatus == OperationalStatus.Up && nic.NetworkInterfaceType != NetworkInterfaceType.Loopback)? .GetPhysicalAddress().ToString();
以下は、最初の操作可能なネットワークインターフェイスのMACアドレスを返すC#コードです。NetworkInterface
アセンブリが他のオペレーティングシステムで使用されるランタイム(つまりMono)で実装されているとすると、これは他のオペレーティングシステムでも機能します。
新しいバージョン:有効な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;
Win32_NetworkAdapterConfiguration WMIクラスのMACAddressプロパティは、アダプターの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 Management Instrumentation)に慣れていない場合は、ここで.NETアプリの概要を説明しています。
WMIは、.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、またはその他のタイプのネットワークアダプターを使用している場合は、別の方法を使用する必要があります。ここにいくつかのオプションがあります:
アイテム#3のサンプルです。これは、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#
WMIを使用して、メトリックが最も低いインターフェイスのMACアドレスを取得します。たとえば、次のように、インターフェイスウィンドウの使用が優先されます。
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;
}
IMHOが最初の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;
}
このメソッドは、指定された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");
ポート番号を指定することもできます。指定しない場合、デフォルトは80です。
更新:
2020
IP接続メトリックが最も低いAVeeのソリューションが本当に気に入っています。ただし、同じメトリックを持つ2番目のNICがインストールされている場合、MACの比較が失敗する可能性があります...
MACとのインターフェースの説明を保存する方が良いでしょう。後の比較では、この文字列によって正しいNICを識別できます。これがサンプルコードです:
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;
}
192.168.0.182というローカルIPを使用するTcpConnectionがあるとします。次に、そのNICのMACアドレスを知りたい場合、meothodを次のように呼び出します。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;
}
この古い投稿を掘り下げるのは本当に嫌いですが、質問はWindows 8-10に固有の別の答えに値すると思います。
Windows.Networking.Connectivity名前空間のNetworkInformationを使用すると、ウィンドウが使用しているネットワークアダプターのIDを取得できます。次に、前述のGetAllNetworkInterfaces()からインターフェイスのMACアドレスを取得できます。
System.Net.NetworkInformationのNetworkInterfaceがGetAllNetworkInterfacesを公開しないため、これはWindowsストアアプリでは機能しません。
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;
}
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);
blak3rのコードを少し変更しました。同じ速度の2つのアダプターがある場合。MACで並べ替えると、常に同じ値が得られます。
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;
}
これを試して:
/// <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;
}