Wie zuverlässig und schnell die MAC-Adresse einer Netzwerkkarte, die angesichts Ihrer Geräte-Instanz-ID
Gegeben Gerät Instanz-ID für eine Netzwerk-Karte, ich würde gerne wissen, Ihre MAC-Adresse. Beispiel Gerät Instanz-ID, die auf meinem system für die integrierte Intel-Gigabit-Karte:
PCI\VEN_8086&DEV_10CC&SUBSYS_00008086&REV_00\3&33FD14CA&0&C8
So weit, der Algorithmus, den ich verwendet haben, funktioniert wie folgt:
- Nennen
SetupDiGetClassDevs
mitDIGCF_DEVICEINTERFACE
. - Nennen
SetupDiEnumDeviceInfo
um das zurückgegebene Gerät in eineSP_DEVINFO_DATA
. - Nennen
SetupDiEnumDeviceInterfaces
mitGUID_NDIS_LAN_CLASS
um eine device-Schnittstelle. - Nennen
SetupDiGetDeviceInterfaceDetail
für diese zurückgegebenen Geräte-Schnittstelle. Dies bringt uns dem Geräte-Pfad als string:\\?\pci#ven_8086&dev_10cc&subsys_00008086&rev_00#3&33fd14ca&0&c8#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{28fd5409-15bd-4c06-b62f-004d3a06f852}
- An dieser Stelle haben wir eine Adresse der Netzwerk-Karte-Treiber-Schnittstelle. Öffnen Sie es mit
CreateFile
über das Ergebnis aus #4. - Nennen
DeviceIoControl
mitIOCTL_NDIS_QUERY_GLOBAL_STATS
und OIDOID_802_3_PERMANENT_ADDRESS
, um die MAC-Adresse.
Dies funktioniert in der Regel, und ist erfolgreich verwendet worden, die auf eine Recht große Anzahl von Maschinen. Es scheint jedoch, dass ganz wenige Maschinen haben den Netzwerk-Treibern, die nicht richtig reagiert, um die DeviceIoControl
Anfrage in Schritt #6; das problem auch nach der Aktualisierung der Netzwerk-Karte-Treiber auf die neueste. Diese sind höher, Windows 7-basierten Computern. Insbesondere DeviceIoControl
erfolgreich ausgeführt, aber es gibt null, bytes statt der erwarteten sechs Byte enthalten die MAC-Adresse.
Einen Anhaltspunkt zu sein scheint, auf der MSDN-Seite für IOCTL_NDIS_QUERY_GLOBAL_STATS
:
Diese IOCTL wird deprecated in späteren Betriebssystem-Versionen. Sie
sollte mit WMI-Schnittstellen zum Abfragen miniport-Treiber Informationen. Für
mehr Informationen finden Sie unter NDIS-Unterstützung für WMI.
-- vielleicht neuere Treiber der Netzwerkkarten sind nicht mehr die Umsetzung dieser IOCTL?
So, wie soll ich damit es funktioniert? Ist es möglich, es ist ein versehen in mein Ansatz und ich mache etwas falsch? Oder muss ich eine ganz andere Herangehensweise? Einige Alternative Ansätze scheinen zu gehören:
- Abfrage
Win32_NetworkAdapter
WMI-Klasse: stellt die benötigten Informationen aber abgelehnt, weil zu schrecklich Leistung. Sehen Schnellen Ersatz für WMI-Klasse Win32_NetworkAdapter für die erste MAC-Adresse des lokalen Computers - Abfrage
MSNdis_EthernetPermanentAddress
WMI-Klasse: erscheint, werden die WMI-Ersatz fürIOCTL_NDIS_QUERY_GLOBAL_STATS
und fragt die OID auch direkt von der Treiber - und dieses funktioniert auf die lästigen Netzwerk-Treiber. Leider werden die zurückgegebenen Instanzen der Klasse nur die MAC-Adresse und dieInstanceName
, das ist eine lokalisierte Zeichenfolge, wieIntel(R) 82567LM-2 Gigabit Network Connection
. AbfragenMSNdis_EnumerateAdapter
ergibt eine Liste, die sich dieInstanceName
zu einemDeviceName
wie\DEVICE\{28FD5409-15BD-4C06-B62F-004D3A06F852}
. Ich bin mir nicht sicher, wie man aus derDeviceName
nach dem plug-and-play-Gerät Instanz-ID (PCI\VEN_8086......
). - Nennen
GetAdaptersAddresses
oderGetAdaptersInfo
(veraltet). Die einzige nicht-lokalisierte Bezeichner, die ich finden kann, ist der Rückgabewert der adapter-Namen, einen string, der wie{28FD5409-15BD-4C06-B62F-004D3A06F852}
- wie dieDeviceName
zurückgegeben, die mit der WMI-NDIS-Klassen. Also nochmal, ich kann nicht herausfinden, wie Sie beziehen sich auf die Geräte-Instanz-ID. Ich bin mir nicht sicher, ob es funktioniert 100% der Zeit, die entweder - z.B. für Adapter, ohne die TCP/IP-Protokoll konfiguriert werden. - NetBIOS-Methode: erfordert spezielle Protokolle eingerichtet werden, die auf der Karte so nicht funktioniert 100% der Zeit. Generell scheint hack-ish, und nicht ein Weg, eine Beziehung zu den Geräte-Instanz-ID, die jedenfalls, die ich kenne. Ich würde dies ablehnen Ansatz.
- Generierung der UUID-Methode: abgelehnt aus Gründen, die ich nicht näher erläutern hier.
Es scheint, dass, wenn ich könnte einen Weg finden, um die "GUID" für die Karte aus dem Gerät Instanz-ID, ich würde mich gut auf meinem Weg mit einem von den beiden verbleibenden Möglichkeiten, Dinge zu tun. Aber ich habe nicht herausgefunden, wie noch. Ansonsten, die WMI-NDIS-Ansatz scheint am meisten Erfolg Versprechen.
Immer eine Liste von Netzwerkkarten und MAC-Adressen ist leicht, und es gibt mehrere Möglichkeiten, es zu tun. Tue es in eine schnelle Art und Weise, die mir erlaubt, Sie beziehen sich auf die Geräte-Instanz-ID ist offenbar schwer...
EDIT: Beispielcode der IOCTL-Aufruf, wenn es hilft jemand (ignorieren Sie die geleckt handle hFile):
HANDLE hFile = CreateFile(dosDevice.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
wcout << "GetMACAddress: CreateFile on " << dosDevice << " failed." << endl;
return MACAddress();
}
BYTE address[6];
DWORD oid = OID_802_3_PERMANENT_ADDRESS, returned = 0;
//this fails too: DWORD oid = OID_802_3_CURRENT_ADDRESS, returned = 0;
if (!DeviceIoControl(hFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid), address, 6, &returned, NULL)) {
DWORD err = GetLastError();
wcout << "GetMACAddress: DeviceIoControl on " << dosDevice << " failed." << endl;
return MACAddress();
}
if (returned != 6) {
wcout << "GetMACAddress: invalid address length of " << returned << "." << endl;
return MACAddress();
}
Der code schlägt fehl, Druck:
GetMACAddress: invalid address length of 0.
Also die DeviceIoControl gibt nicht-null Erfolg, aber wieder null bytes.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist ein Weg, es zu tun:
GetAdaptersAddresses
, um eine Liste derIP_ADAPTER_ADDRESSES
StrukturenAdapterName
Feld (ich bin mir nicht sicher, ob dieses Verhalten garantiert, aber alle Adapter in meinem system eine GUID hier, und die Dokumentation sagt das derAdapterName
permanent)HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\<the adapter GUID>\Connection\PnPInstanceID
(falls vorhanden) (diese Idee kam von hier; die Suche auf Google, der Schlüssel scheint zu gut dokumentiert, so ist es wahrscheinlich nicht zu ändern)PCI\VEN_14E4&DEV_16B1&SUBSYS_96B11849&REV_10\4&2B8260C3&0&00E4
)IP_ADAPTER_ADDRESSES
und Blick auf diePhysicalAddress
FeldEs wäre nicht Windows, wenn es nicht eine million Möglichkeiten, etwas zu tun!
Gewickelt ich mit
SetupDiGetDeviceRegistryProperty
zu LesenSPDRP_FRIENDLYNAME
. Wenn das nicht gefunden wird, dann lese ichSPDRP_DEVICEDESC
statt. Letztlich bekommt von mir eine Zeichenkette, wie "VirtualBox Host-only Ethernet Adapter #2". Ich habe dann mit dieser gegen die InstanceName-Eigenschaft der WMI-NDIS-Klassen (MSNdis_EthernetPermanentAddress
WMI-Klasse). Beide Eigenschaften müssen gelesen werden, im Fall es sind mehrere Adapter teilen den gleichen Treiber (z.B. "#2", "#3", etc.) - wenn es nur einen adapter dannSPDRP_FRIENDLYNAME
ist nicht verfügbar, aber wenn es mehr als eine, dannSPDRP_FRIENDLYNAME
ist erforderlich, um Sie zu unterscheiden.Die Methode macht mich ein wenig nervös, weil ich Vergleiche, was scheint wie eine lokalisierte Zeichenfolge, und es gibt keine Dokumentation, die ich gefunden habe, die garantiert, was ich Tue, wird immer funktionieren. Leider habe ich nicht gefunden keine besseren Möglichkeiten, die dokumentiert sind, um zu arbeiten, entweder.
Ein paar andere Alternative Methoden umfassen kriechen in undokumentierten registry-Standorten. Eine Methode ist spencercw ' s Methode, und der andere wäre zu Lesen
SPDRP_DRIVER
, das ist der name eines Unterschlüssels unterHKLM\SYSTEM\CurrentControlSet\Control\Class
. Unter die Fahrer-Taste, suchen Sie dieLinkage\Export
- Wert, dann scheint, wie es könnte sein, abgestimmt auf dieDeviceName
Eigenschaft desMSNdis_EnumerateAdapter
Klasse. Aber es gibt keine Unterlagen, die ich finden konnte, sagt diese Werte können rechtlich abgestimmt. Außerdem, die einzigen Unterlagen, die ich zum Thema gefundenLinkage\Export
wurde von der Win2000 Referenz zur Registrierung und ausdrücklich gesagt, dass die Anwendungen sollten nicht auf Sie verlassen.Wäre eine andere Methode zu suchen, bei meiner ursprünglichen Frage, Schritt 4: "
SetupDiGetDeviceInterfaceDetail
für diese zurückgegeben device interface". Der Gerät-Schnittstelle, Pfad tatsächlich kann verwendet werden, um zu rekonstruieren, das Gerät Weg. Start mit device interface path:\\?\pci#ven_8086&dev_10cc&subsys_00008086&rev_00#3&33fd14ca&0&c8#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{28fd5409-15bd-4c06-b62f-004d3a06f852}
. Entfernen Sie dann alles vor dem letzten slash, verlassen Sie mit:{28fd5409-15bd-4c06-b62f-004d3a06f852}
. Schließlich, stellen Sie\Device\
auf diese Zeichenfolge, und es passen gegen die WMI-NDIS-Klassen. Wieder, dies scheint jedoch zu sein, ohne Papiere und unter Berufung auf eine Implementierung detail of a device interface Weg.In der end, die andere Methoden, die ich untersucht hatte Ihre eigene, nicht dokumentierte Komplikationen, Klang zumindest so ernst, wie passend zu den
SPDRP_FRIENDLYNAME
/SPDRP_DEVICEDESC
strings. So entschied ich mich für die einfachere Ansatz, die genau denen entsprechen, die Saiten gegen das WMI-NDIS-Klassen.Ich vermute, Sie möchten Holen Sie sich die MAC-Adresse, um zu implementieren eine Art von DRM -, Inventar-oder Klassensystem, da Sie versucht, die permanente MAC-Adresse anstelle der aktuellen eine.
Du scheinst zu vergessen, dass es auch eine administrativ super-auferlegt MAC-Adresse (in anderen Worten: ein "Zwang" MAC-Adresse).
Einige Treiber lassen Sie diese vom Gerät-Eigenschaft Seite, unter der Registerkarte "Erweitert" (zum Beispiel: meine Marvell Netzwerkkarte lassen Sie mich dies zu tun), während andere nicht lassen Sie tun, dass Sie (lies: Sie unterstützen nicht die Eigenschaft).
Aber alles endet in einer Registry-Wert:
HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\xxxx\NetworkAddress
mitREG_SZ
geben.Hier können Sie eine andere MAC-Adresse als die ursprüngliche, in der form "01020304abcd" (6 bytes, plain hexadezimal, ohne
:
Separatoren oder0x
Präfix).Nachdem Sie es einrichten, starten Sie den Computer neu, und auf power-up-die neue MAC-Adresse haben-Effekt.
Durch Zufall habe ich ein Mainboard mit zwei integrierten Marvell Netzwerkkarten und einen NETGEAR USB-WLAN-NIC. Der Marvell unterstützt das ändern der MAC-Adresse: wenn Sie die
NetworkAddress
Wert in die Registry, sehen Sie den neuen Wert in den Treiber-Eigenschaften, Seite, zu, und es wirkt sofort, ohne die Notwendigkeit, neu zu starten (wenn Sie es ändern von device-Eigenschaft Seite).Hier finden Sie die Ergebnisse Auslesen der MAC-Adresse mit verschiedenen Methoden:
GetAdaptersInfo
: neue MAC-AdresseIOCTL_NDIS_QUERY_GLOBAL_STATS
: original-MAC-AdresseMSNdis_EthernetPermanentAddress
: original-MAC-AdresseHabe ich versucht, indem die
NetworkAddress
Wert in der Registry für den NETGEAR USB-WLAN-NIC, und die Ergebnisse sind:GetAdaptersInfo
: neue MAC-AdresseIOCTL_NDIS_QUERY_GLOBAL_STATS
: neue MAC-AdresseMSNdis_EthernetPermanentAddress
: neue MAC-AdresseDie original-MAC-Adresse verschwunden ist.
Also, um nicht getäuscht werden, indem ein Benutzer mit bösartigen Absichten, Sie müssen immer überprüfen Sie die
HKLM\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\xxxx\NetworkAddress
Registry-Wert. Wenn das eingestellt ist, ich denke, es ist besser zu nicht darauf Vertrauen, dass der Netzwerk-Adapter an alle, da ist es an der Treiber-Implementierung zu entscheiden, was wird Ihnen präsentiert, die mit unterschiedlichen Methoden.Einige Hintergrundinformationen für immer zu, dass Registry-Schlüssel:
Microsoft-Dokumentation über die HKLM\SYSTEM\CurrentControlSet\Class key
Laut der Microsoft-Dokumentation auf dieser Seite,
So wählen wir die
{4D36E972-E325-11CE-BFC1-08002BE10318}
Unterschlüssel (akaGUID_DEVCLASS_NET
, definiert in<devguid.h>
, und weiter dokumentiert hier)Wieder laut Microsoft-Dokumentation,
So können Sie durchqueren den Unterschlüssel aus 0000, 0001, 0002, bis zu der Anzahl der Netzwerk-Adapter in Ihrem system.
Die Dokumentation bleibt hier: ich fand keine andere Dokumentation über die verschiedenen registry-Werten oder so.
Jedoch in jedem dieser Unterschlüssel können, finden Sie die REG_SZ Werte, die helfen können, verknüpfen Sie den
GetAdaptersInfo()
,MSNdis_EthernetPermanentAddress
,Win32_NetworkAdapter
- und Geräte-Instanz-ID Welten (und deine Frage damit beantwortet ist).Sind die Registry-Werte:
DeviceInstanceID
: sein Wert ist keine überraschung, das Gerät Instanz-IDNetCfgInstanceId
: sein Wert ist derAdapterName
Mitglied derIP_ADAPTER_INFO
struct zurückgegebenGetAdaptersInfo()
. Es ist auch dieGUID
Mitglied derWin32_NetworkAdapter
WMI-Klasse.NetworkAddress
: soll eine gültige MAC-Adresse gibt es hier ein Treiber kann Bericht als auch die MAC-Adresse im Gebrauch durchGetAdaptersInfo()
,MSNdis_EthernetPermanentAddress
, undIOCTL_NDIS_QUERY_GLOBAL_STATS
!Dann, wie du schon sagtest, die einzige Verbindung zwischen den
MSNdis_EthernetPermanentAddress
WMI-Klasse und dem rest der "Welt" ist durch seineInstanceName
Mitglied. Sie können Sie beziehen sich auf dieDescription
Mitglied derIP_ADAPTER_INFO
struct zurückgegebenGetAdaptersInfo()
. Obwohl es sein kann eine lokalisierte Namen, es scheint einzigartig zu sein für das system (Für meine zwei integrierten Marvell Netzwerkkarten, die zweite hat ein "#2" angehängt, um den Namen).Letzte Anmerkung:
Alles gesagt oben, der Benutzer kann wählen, zu deaktivieren WMI...