是否可以在不使用WMI的情况下获得网络适配器的PnPDeviceId?

我一直试图使用p / invoke setupapi调用获取给定网络适配器的PnPDeviceId但没有成功。 我不情愿地决定使用WMI,如下所示:

public static string GetPnpDeviceId(string mac) { ManagementObjectCollection mo = Management.GetCollection("Win32_NetworkAdapter", "PNPDeviceID", "MACAddress = '" + mac + "'"); return GetFirstValueString(mo, "PNPDeviceID"); } public static ManagementObjectCollection GetCollection(string WMIClass, string WMISelect="*", string WMIWhere="") { string qry = "SELECT " + WMISelect + " FROM " + WMIClass + (WMIWhere == "" ? "" : " WHERE " + WMIWhere); ObjectQuery oq = new System.Management.ObjectQuery(qry); ManagementObjectSearcher query = new ManagementObjectSearcher(oq); ManagementObjectCollection queryCollection = query.Get(); return queryCollection; } public static string GetFirstValueString(ManagementObjectCollection queryCollection, string WMIValue) { foreach (ManagementObject mo in queryCollection) { object o = mo[WMIValue]; return (string)o; } return ""; } 

p / invoke apis看起来很复杂,但是为这样一个简单的调用加载管理类(特别是Win32_NetworkAdapter)的开销似乎过大了。 任何人都可以告诉我,如果这是可能的,即使使用p / invoke或更好仍然告诉我在api调用中找到值的位置,我将从那里开始。

好吧,我自己解决了。 这是很多代码,但性能是值得的imho。 WMI调用每个大约需要800毫秒,而pinvoke调用大约需要25毫秒。 无论如何这里是代码(粗略和准备好的评论):

 class NetPnP { internal static Guid GUID_DEVINTERFACE_NET = new Guid("CAC88484-7515-4C03-82E6-71A87ABAC361"); public static string GetPnPDeviceId(NetworkInterface ni) { Guid classGuid = GUID_DEVINTERFACE_NET; IntPtr hwndParent = IntPtr.Zero; Int32 flags = Win32DeviceMgmt.DIGCF_DEVICEINTERFACE | Win32DeviceMgmt.DIGCF_PRESENT; IntPtr pDevInfoSet = IntPtr.Zero; IntPtr pNewDevInfoSet = IntPtr.Zero; try { pNewDevInfoSet = Win32DeviceMgmt.SetupDiGetClassDevs(ref classGuid, IntPtr.Zero, hwndParent, flags);//, pDevInfoSet, strMachineName, IntPtr.Zero); if (pNewDevInfoSet == IntPtr.Zero) { Logger.Log("Failed to get device information list"); return ""; } Int32 iRet; Int32 iMemberIndex = 0; do { Win32DeviceMgmt.SP_DEVINFO_DATA devInfoData = new Win32DeviceMgmt.SP_DEVINFO_DATA(); devInfoData.ClassGuid = Guid.Empty; devInfoData.DevInst = 0; devInfoData.Reserved = UIntPtr.Zero; devInfoData.cbSize = Marshal.SizeOf(devInfoData); iRet = Win32DeviceMgmt.SetupDiEnumDeviceInfo(pNewDevInfoSet, iMemberIndex, ref devInfoData); if (iRet == 0) { Int32 iLastError = Win32DeviceMgmt.GetLastError(); if (iLastError == Win32DeviceMgmt.ERROR_NO_MORE_FILES) { //Console.WriteLine("No more devices in list"); break; } else { iMemberIndex++; continue; } } string desc = GetDevicePropertyString(pNewDevInfoSet, devInfoData, SetupDiGetDeviceRegistryPropertyEnum.SPDRP_DEVICEDESC); if (ni.Description.Equals(desc)) return GetDeviceInstanceId(pNewDevInfoSet, devInfoData); string friendly = GetDevicePropertyString(pNewDevInfoSet, devInfoData, SetupDiGetDeviceRegistryPropertyEnum.SPDRP_FRIENDLYNAME); if (ni.Description.Equals(friendly)) return GetDeviceInstanceId(pNewDevInfoSet, devInfoData); iMemberIndex++; } while (true); return ""; } finally { Win32DeviceMgmt.SetupDiDestroyDeviceInfoList(pNewDevInfoSet); } } static String GetDeviceInstanceId(IntPtr DeviceInfoSet, Win32DeviceMgmt.SP_DEVINFO_DATA DeviceInfoData) { StringBuilder strId = new StringBuilder(0); Int32 iRequiredSize = 0; Int32 iSize = 0; Int32 iRet = Win32DeviceMgmt.SetupDiGetDeviceInstanceId(DeviceInfoSet, ref DeviceInfoData, strId, iSize, ref iRequiredSize); strId = new StringBuilder(iRequiredSize); iSize = iRequiredSize; iRet = Win32DeviceMgmt.SetupDiGetDeviceInstanceId(DeviceInfoSet, ref DeviceInfoData, strId, iSize, ref iRequiredSize); if (iRet == 1) { return strId.ToString(); } return String.Empty; } static String GetDevicePropertyString(IntPtr DeviceInfoSet, Win32DeviceMgmt.SP_DEVINFO_DATA DeviceInfoData, SetupDiGetDeviceRegistryPropertyEnum property) { byte[] ptrBuf = GetDeviceProperty(DeviceInfoSet, DeviceInfoData, property); return ptrBuf.ToStrAuto(); } static Guid GetDevicePropertyGuid(IntPtr DeviceInfoSet, Win32DeviceMgmt.SP_DEVINFO_DATA DeviceInfoData, SetupDiGetDeviceRegistryPropertyEnum property) { byte[] ptrBuf = GetDeviceProperty(DeviceInfoSet, DeviceInfoData, property); return new Guid(ptrBuf); } static byte[] GetDeviceProperty(IntPtr DeviceInfoSet, Win32DeviceMgmt.SP_DEVINFO_DATA DeviceInfoData, SetupDiGetDeviceRegistryPropertyEnum property) { StringBuilder strId = new StringBuilder(0); byte[] ptrBuf= null; UInt32 RegType; UInt32 iRequiredSize = 0; UInt32 iSize = 0; bool iRet = Win32DeviceMgmt.SetupDiGetDeviceRegistryProperty(DeviceInfoSet, ref DeviceInfoData, (uint)property, out RegType, ptrBuf, iSize, out iRequiredSize); ptrBuf = new byte[iRequiredSize]; iSize = iRequiredSize; iRet = Win32DeviceMgmt.SetupDiGetDeviceRegistryProperty(DeviceInfoSet, ref DeviceInfoData, (uint)property, out RegType, ptrBuf, iSize, out iRequiredSize); if (iRet) { return ptrBuf; } return new byte[0]; } } public static class ByteArrayEx { public static string ToStrAuto(this byte[] bytes) { string ret = ""; IntPtr unmanagedPointer = Marshal.AllocHGlobal(bytes.Length); try { Marshal.Copy(bytes, 0, unmanagedPointer, bytes.Length); // Call unmanaged code ret = Marshal.PtrToStringAuto(unmanagedPointer); } finally { Marshal.FreeHGlobal(unmanagedPointer); } return ret; } } public class Win32DeviceMgmt { internal static Int32 ERROR_NO_MORE_FILES = 259; internal static Int32 LINE_LEN = 256; internal static Int32 DIGCF_DEFAULT = 0x00000001; // only valid with DIGCF_DEVICEINTERFACE internal static Int32 DIGCF_PRESENT = 0x00000002; internal static Int32 DIGCF_ALLCLASSES = 0x00000004; internal static Int32 DIGCF_PROFILE = 0x00000008; internal static Int32 DIGCF_DEVICEINTERFACE = 0x00000010; internal static Int32 SPINT_ACTIVE = 0x00000001; internal static Int32 SPINT_DEFAULT = 0x00000002; internal static Int32 SPINT_REMOVED = 0x00000004; [StructLayout(LayoutKind.Sequential)] internal struct SP_DEVINFO_DATA { ///  /// Size of structure in bytes ///  public Int32 cbSize; ///  /// GUID of the device interface class ///  public Guid ClassGuid; ///  /// Handle to this device instance ///  public Int32 DevInst; ///  /// Reserved; do not use. ///  public UIntPtr Reserved; }; [StructLayout(LayoutKind.Sequential)] internal struct SP_DEVICE_INTERFACE_DATA { ///  /// Size of the structure, in bytes ///  public Int32 cbSize; ///  /// GUID of the device interface class ///  public Guid InterfaceClassGuid; ///  /// ///  public Int32 Flags; ///  /// Reserved; do not use. ///  public IntPtr Reserved; }; [DllImport("setupapi.dll")] internal static extern IntPtr SetupDiGetClassDevsEx(ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPStr)]String enumerator, IntPtr hwndParent, Int32 Flags, IntPtr DeviceInfoSet, [MarshalAs(UnmanagedType.LPStr)]String MachineName, IntPtr Reserved); [DllImport("setupapi.dll", CharSet = CharSet.Auto)] internal static extern IntPtr SetupDiGetClassDevs( // 1st form using a ClassGUID only, with null Enumerator ref Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, int Flags ); [DllImport("setupapi.dll")] internal static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); [DllImport("setupapi.dll")] internal static extern Int32 SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, IntPtr InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVINFO_DATA DeviceInterfaceData); [DllImport("setupapi.dll")] internal static extern Int32 SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, Int32 MemberIndex, ref SP_DEVINFO_DATA DeviceInterfaceData); [DllImport("setupapi.dll")] internal static extern Int32 SetupDiClassNameFromGuid(ref Guid ClassGuid, StringBuilder className, Int32 ClassNameSize, ref Int32 RequiredSize); [DllImport("setupapi.dll")] internal static extern Int32 SetupDiGetClassDescription(ref Guid ClassGuid, StringBuilder classDescription, Int32 ClassDescriptionSize, ref Int32 RequiredSize); [DllImport("setupapi.dll")] internal static extern Int32 SetupDiGetDeviceInstanceId( IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, StringBuilder DeviceInstanceId, Int32 DeviceInstanceIdSize, ref Int32 RequiredSize); ///  /// The SetupDiGetDeviceRegistryProperty function retrieves the specified device property. /// This handle is typically returned by the SetupDiGetClassDevs or SetupDiGetClassDevsEx function. ///  /// Handle to the device information set that contains the interface and its underlying device. /// Pointer to an SP_DEVINFO_DATA structure that defines the device instance. /// Device property to be retrieved. SEE MSDN /// Pointer to a variable that receives the registry data Type. This parameter can be NULL. /// Pointer to a buffer that receives the requested device property. /// Size of the buffer, in bytes. /// Pointer to a variable that receives the required buffer size, in bytes. This parameter can be NULL. /// If the function succeeds, the return value is nonzero. [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern bool SetupDiGetDeviceRegistryProperty( IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, uint Property, out UInt32 PropertyRegDataType, byte[] PropertyBuffer, uint PropertyBufferSize, out UInt32 RequiredSize ); // Device Property [StructLayout(LayoutKind.Sequential)] internal struct DEVPROPKEY { public Guid fmtid; public UInt32 pid; } [DllImport("kernel32.dll")] internal static extern Int32 GetLastError(); } ///  /// Flags for SetupDiGetDeviceRegistryProperty(). ///  enum SetupDiGetDeviceRegistryPropertyEnum : uint { SPDRP_DEVICEDESC = 0x00000000, // DeviceDesc (R/W) SPDRP_HARDWAREID = 0x00000001, // HardwareID (R/W) SPDRP_COMPATIBLEIDS = 0x00000002, // CompatibleIDs (R/W) SPDRP_UNUSED0 = 0x00000003, // unused SPDRP_SERVICE = 0x00000004, // Service (R/W) SPDRP_UNUSED1 = 0x00000005, // unused SPDRP_UNUSED2 = 0x00000006, // unused SPDRP_CLASS = 0x00000007, // Class (R--tied to ClassGUID) SPDRP_CLASSGUID = 0x00000008, // ClassGUID (R/W) SPDRP_DRIVER = 0x00000009, // Driver (R/W) SPDRP_CONFIGFLAGS = 0x0000000A, // ConfigFlags (R/W) SPDRP_MFG = 0x0000000B, // Mfg (R/W) SPDRP_FRIENDLYNAME = 0x0000000C, // FriendlyName (R/W) SPDRP_LOCATION_INFORMATION = 0x0000000D, // LocationInformation (R/W) SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000E, // PhysicalDeviceObjectName (R) SPDRP_CAPABILITIES = 0x0000000F, // Capabilities (R) SPDRP_UI_NUMBER = 0x00000010, // UiNumber (R) SPDRP_UPPERFILTERS = 0x00000011, // UpperFilters (R/W) SPDRP_LOWERFILTERS = 0x00000012, // LowerFilters (R/W) SPDRP_BUSTYPEGUID = 0x00000013, // BusTypeGUID (R) SPDRP_LEGACYBUSTYPE = 0x00000014, // LegacyBusType (R) SPDRP_BUSNUMBER = 0x00000015, // BusNumber (R) SPDRP_ENUMERATOR_NAME = 0x00000016, // Enumerator Name (R) SPDRP_SECURITY = 0x00000017, // Security (R/W, binary form) SPDRP_SECURITY_SDS = 0x00000018, // Security (W, SDS form) SPDRP_DEVTYPE = 0x00000019, // Device Type (R/W) SPDRP_EXCLUSIVE = 0x0000001A, // Device is exclusive-access (R/W) SPDRP_CHARACTERISTICS = 0x0000001B, // Device Characteristics (R/W) SPDRP_ADDRESS = 0x0000001C, // Device Address (R) SPDRP_UI_NUMBER_DESC_FORMAT = 0X0000001D, // UiNumberDescFormat (R/W) SPDRP_DEVICE_POWER_DATA = 0x0000001E, // Device Power Data (R) SPDRP_REMOVAL_POLICY = 0x0000001F, // Removal Policy (R) SPDRP_REMOVAL_POLICY_HW_DEFAULT = 0x00000020, // Hardware Removal Policy (R) SPDRP_REMOVAL_POLICY_OVERRIDE = 0x00000021, // Removal Policy Override (RW) SPDRP_INSTALL_STATE = 0x00000022, // Device Install State (R) SPDRP_LOCATION_PATHS = 0x00000023, // Device Location Paths (R) SPDRP_BASE_CONTAINERID = 0x00000024 // Base ContainerID (R) }