2012-09-26 30 views
7

नेटवर्क कार्ड के लिए device instance ID को देखते हुए, मैं इसका मैक पता जानना चाहता हूं। एकीकृत इंटेल गीगाबिट कार्ड के लिए अपने सिस्टम पर उदाहरण डिवाइस उदाहरण ID:नेटवर्क कार्ड के एमएसी पते को विश्वसनीय और तेज़ी से कैसे प्राप्त करें, इसके डिवाइस इंस्टेंस आईडी

PCI\VEN_8086&DEV_10CC&SUBSYS_00008086&REV_00\3&33FD14CA&0&C8 

अब तक, एल्गोरिथ्म मैं के रूप में काम करता है का इस्तेमाल किया है इस प्रकार है:

  1. DIGCF_DEVICEINTERFACE साथ कॉल SetupDiGetClassDevs
  2. पर SP_DEVINFO_DATA में लौटा डिवाइस प्राप्त करने के लिए कॉल करें।
  3. डिवाइस इंटरफ़ेस प्राप्त करने के लिए GUID_NDIS_LAN_CLASS के साथ SetupDiEnumDeviceInterfaces पर कॉल करें।
  4. इस लौटे डिवाइस इंटरफ़ेस के लिए SetupDiGetDeviceInterfaceDetail पर कॉल करें। यह हमें स्ट्रिंग के रूप में डिवाइस पथ प्राप्त करता है: \\?\pci#ven_8086&dev_10cc&subsys_00008086&rev_00#3&33fd14ca&0&c8#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{28fd5409-15bd-4c06-b62f-004d3a06f852}
  5. इस बिंदु पर हमारे पास नेटवर्क कार्ड ड्राइवर के इंटरफ़ेस का पता है। # 4 से परिणाम का उपयोग कर CreateFile के साथ इसे खोलें।
  6. DeviceIoControlIOCTL_NDIS_QUERY_GLOBAL_STATS और OID_802_3_PERMANENT_ADDRESS के ओआईडी को एमएसी पता प्राप्त करने के लिए कॉल करें।

यह आमतौर पर काम करता है, और बड़ी संख्या में मशीनों पर सफलतापूर्वक उपयोग किया गया है। हालांकि, ऐसा लगता है कि बहुत ही चुनिंदा कुछ मशीनों में नेटवर्क ड्राइवर हैं जो चरण # 6 में DeviceIoControl अनुरोध के लिए ठीक से प्रतिक्रिया नहीं दे रहे हैं; नेटवर्क कार्ड ड्राइवरों को नवीनतम अद्यतन करने के बाद भी समस्या बनी रहती है। ये नए, विंडोज 7-आधारित कंप्यूटर हैं। विशेष रूप से, DeviceIoControl सफलतापूर्वक पूर्ण हो जाता है, लेकिन मैक पते वाले अपेक्षित छह बाइट्स के बजाय शून्य बाइट देता है।

एक सुराग IOCTL_NDIS_QUERY_GLOBAL_STATS के लिए MSDN पृष्ठ पर हो रहा है:

इस IOCTL बाद में ऑपरेटिंग सिस्टम के रिलीज में हटा दिया जाएगा। आप को मिनीपोर्ट ड्राइवर जानकारी पूछने के लिए WMI इंटरफेस का उपयोग करना चाहिए। के लिए अधिक जानकारी देखें, डब्ल्यूएमआई के लिए एनडीआईएस समर्थन।

- शायद नए नेटवर्क कार्ड ड्राइवर अब इस आईओसीटीएल को लागू नहीं कर रहे हैं?

तो, मुझे यह कैसे काम करना चाहिए? क्या यह संभव है कि मेरे दृष्टिकोण में एक निरीक्षण हो और मैं कुछ गलत कर रहा हूं? या मुझे एक और अधिक अलग दृष्टिकोण लेने की ज़रूरत है? कुछ वैकल्पिक दृष्टिकोणों में शामिल हैं:

  • क्वेरी Win32_NetworkAdapter डब्ल्यूएमआई कक्षा: आवश्यक जानकारी प्रदान करता है लेकिन भयानक प्रदर्शन के कारण खारिज कर दिया जाता है। देखें Fast replacement for Win32_NetworkAdapter WMI class for getting MAC address of local computer
  • क्वेरी MSNdis_EthernetPermanentAddress डब्ल्यूएमआई कक्षा: IOCTL_NDIS_QUERY_GLOBAL_STATS के लिए डब्लूएमआई प्रतिस्थापन प्रतीत होता है और ओआईडी से सीधे ड्राइवर से पूछताछ करता है - और यह परेशानी नेटवर्क ड्राइवर पर काम करता है। दुर्भाग्यवश, लौटा वर्ग उदाहरण केवल मैक पता और InstanceName प्रदान करता है, जो Intel(R) 82567LM-2 Gigabit Network Connection जैसी स्थानीयकृत स्ट्रिंग है। MSNdis_EnumerateAdapter क्वेरीिंग InstanceNameDeviceName से \DEVICE\{28FD5409-15BD-4C06-B62F-004D3A06F852} जैसी एक सूची उत्पन्न करती है। मुझे यकीन नहीं है कि DeviceName से प्लग-एंड-प्ले डिवाइस इंस्टेंस आईडी (PCI\VEN_8086......) पर कैसे जाना है।
  • GetAdaptersAddresses या GetAdaptersInfo (बहिष्कृत) पर कॉल करें। रिटर्न वैल्यू में मुझे एकमात्र गैर-स्थानीय पहचानकर्ता मिल सकता है एडाप्टर नाम, जो {28FD5409-15BD-4C06-B62F-004D3A06F852} जैसी स्ट्रिंग है - WMI NDIS कक्षाओं द्वारा लौटाए गए DeviceName के समान। तो फिर, मैं यह नहीं समझ सकता कि इसे डिवाइस इंस्टेंस आईडी से कैसे जोड़ना है। मुझे यकीन नहीं है कि यह समय के 100% काम करेगा - उदा। टीसीपी/आईपी प्रोटोकॉल के बिना एडेप्टर के लिए कॉन्फ़िगर किया गया।
  • नेटबीओएस विधि: कार्ड पर विशिष्ट प्रोटोकॉल स्थापित करने की आवश्यकता है, इसलिए 100% समय काम नहीं करेगा। आम तौर पर हैक-आश लगता है, और डिवाइस इंस्टेंस आईडी से संबंधित कोई तरीका नहीं है जिसे मैं जानता हूं। मैं इस दृष्टिकोण को अस्वीकार कर दूंगा।
  • यूयूआईडी पीढ़ी विधि: उन कारणों से खारिज कर दिया गया है जिन पर मैं विस्तार नहीं करूंगा।

ऐसा लगता है कि मुझे डिवाइस इंस्टेंस आईडी से कार्ड के लिए "GUID" प्राप्त करने का कोई तरीका मिल सकता है, तो मैं चीजों को करने के शेष दो तरीकों में से एक के साथ अपने रास्ते पर अच्छा होगा। लेकिन मुझे अभी तक पता नहीं चला है कि कैसे। अन्यथा, डब्लूएमआई एनडीआईएस दृष्टिकोण सबसे अधिक आशाजनक प्रतीत होता है।

नेटवर्क कार्ड और मैक पते की एक सूची प्राप्त करना आसान है, और इसे करने के कई तरीके हैं। एक तेजी से रास्ता मुझे डिवाइस उदाहरण आईडी करने के लिए इसे संबंधित देता है कि में यह कर जाहिरा तौर पर मुश्किल है ...

संपादित करें: IOCTL कॉल की नमूना कोड अगर यह मदद करता है किसी को भी (लीक 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(); 
} 

कोड विफल रहता है, मुद्रण:

GetMACAddress: invalid address length of 0. 

तो DeviceIoControl रिटर्न गैर शून्य सफलता का संकेत है, लेकिन फिर शून्य बाइट्स देता है।

उत्तर

2

SPDRP_FRIENDLYNAME पढ़ने के लिए SetupDiGetDeviceRegistryProperty का उपयोग करके घायल हो गया। यदि यह नहीं मिला है, तो मैं इसके बजाय SPDRP_DEVICEDESC पढ़ता हूं। आखिरकार, यह मुझे "वर्चुअलबॉक्स होस्ट-केवल ईथरनेट एडाप्टर # 2" जैसी स्ट्रिंग प्राप्त करता है। इसके बाद मैं डब्लूएमआई एनडीआईएस कक्षाओं (MSNdis_EthernetPermanentAddress डब्लूएमआई कक्षा) में इंस्टेंसनाम संपत्ति के खिलाफ इसका मिलान करता हूं।दोनों गुणों को उसी ड्राइवर को साझा करने वाले एकाधिक एडेप्टर (यानी "# 2", "# 3" इत्यादि) में पढ़ा जाना चाहिए - यदि केवल एक एडाप्टर है तो SPDRP_FRIENDLYNAME उपलब्ध नहीं है, लेकिन यदि एक से अधिक हैं तो SPDRP_FRIENDLYNAME उन्हें अलग करने के लिए आवश्यक है।

विधि मुझे थोड़ा परेशान करती है क्योंकि मैं स्थानीयकृत स्ट्रिंग की तरह दिखने की तुलना कर रहा हूं, और मुझे कोई दस्तावेज नहीं मिला है जो मुझे लगता है कि मैं जो कर रहा हूं वह हमेशा काम करेगा। दुर्भाग्य से, मुझे कोई बेहतर तरीका नहीं मिला है जो काम करने के लिए प्रलेखित हैं।

कुछ अन्य वैकल्पिक तरीकों में अनियंत्रित रजिस्ट्री स्थानों में घबराहट शामिल है। एक विधि spencercw की विधि है, और दूसरा SPDRP_DRIVER पढ़ना होगा, जो HKLM\SYSTEM\CurrentControlSet\Control\Class के तहत उपकुंजी का नाम है। ड्राइवर कुंजी के नीचे, Linkage\Export मान देखें, जो ऐसा लगता है कि MSNdis_EnumerateAdapter कक्षा की संपत्ति से मेल खाया जा सकता है। लेकिन मुझे कोई दस्तावेज नहीं मिला है जो कह सकता है कि ये मान कानूनी रूप से मेल खाते हैं। इसके अलावा, Linkage\Export के बारे में मुझे मिला एकमात्र दस्तावेज Win2000 रजिस्ट्री संदर्भ से था और स्पष्ट रूप से कहा गया था कि अनुप्रयोगों पर भरोसा नहीं करना चाहिए।

एक और तरीका मेरे मूल प्रश्न को देखने के लिए होगा, चरण 4: "SetupDiGetDeviceInterfaceDetail इस लौटा डिवाइस इंटरफ़ेस के लिए"। उपकरण इंटरफ़ेस पथ का उपयोग वास्तव में डिवाइस पथ को पुनर्निर्माण के लिए किया जा सकता है। डिवाइस इंटरफ़ेस पथ से प्रारंभ करें: \\?\pci#ven_8086&dev_10cc&subsys_00008086&rev_00#3&33fd14ca&0&c8#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{28fd5409-15bd-4c06-b62f-004d3a06f852}। फिर, अंतिम स्लैश से पहले सबकुछ हटा दें, आपको {28fd5409-15bd-4c06-b62f-004d3a06f852} के साथ छोड़ दें। अंत में, इस स्ट्रिंग में \Device\ प्रीपेड करें और इसे WMI NDIS कक्षाओं के विरुद्ध मेल करें। फिर भी, यह अनियंत्रित प्रतीत होता है और डिवाइस इंटरफ़ेस पथ के कार्यान्वयन विवरण पर निर्भर करता है।

अंत में, मैंने जिन अन्य तरीकों की जांच की थी, उनकी अपनी अनियंत्रित जटिलताओं में कम से कम SPDRP_FRIENDLYNAME/SPDRP_DEVICEDESC तारों से मेल खाने के रूप में गंभीर रूप से गंभीर लग रहा था। इसलिए मैंने सरल दृष्टिकोण का चयन किया, जो कि डब्लूएमआई एनडीआईएस कक्षाओं के खिलाफ उन तारों से मेल खाता था।

4

यहाँ एक तरीका है यह करने के लिए:

  1. कॉल GetAdaptersAddresses प्रत्येक अनुकूलक पर IP_ADAPTER_ADDRESSES structs
  2. दोहराएं की एक सूची प्राप्त और AdapterName क्षेत्र से अपने GUID प्राप्त करने के लिए (मैं इस व्यवहार करता है, तो यकीन नहीं है इसकी गारंटी है, लेकिन मेरे सिस्टम में सभी एडेप्टरों के पास एक GUID है, और प्रलेखन का कहना है कि AdapterName स्थायी है)
  3. प्रत्येक एडाप्टर के लिए HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\<the adapter GUID>\Connection\PnPInstanceID (यदि यह मौजूद है) से रजिस्ट्री कुंजी को पढ़ें (इस विचार को here से प्राप्त करें; searchin गूगल पर छ कि कुंजी अच्छी तरह से प्रलेखित किया जा रहा है, तो यह इस कुंजी आप (एडाप्टर के लिए डिवाइस आईडी प्राप्त करने की तरह कुछ से बदलने की संभावना)
  4. नहीं है: PCI\VEN_14E4&DEV_16B1&SUBSYS_96B11849&REV_10\4&2B8260C3&0&00E4)
  5. प्रत्येक एडाप्टर के लिए ऐसा करें जब तक आप एक पाते हैं मैच। जब आप अपने मैच मिल सिर्फ IP_ADAPTER_ADDRESSES के लिए वापस जाओ और PhysicalAddress क्षेत्र
  6. पर देखने के एक बियर (वैकल्पिक) जाओ

यह Windows अगर वहाँ कुछ करने के लिए एक लाख तरीके नहीं थे नहीं होगा!

+0

मान .. आपने मेरे गधे को यहां बचाया। बहुत बहुत धन्यवाद। – Pyjong