C# 使用SetupAPI获取windows系统设备管理器相关信息
因工作需要,要获取windows系统上设备管理器里的设备信息、设备驱动信息。
最开始是使用WMI来获取,但是测试后发现有一些不足:查询速度慢,查询信息分散,需要的信息没有,再就是耗时长,需要查询资料。
之后在网上查询有没有更好的方法来获取,就找到了SetupAPI。可以通过几个函数来获取相关信息。网上的是示例大部分都是C++,少部分是C#,C#的示例功能也不多,我通过网上的C++、C#示例和代码测试,对使用SetupAPI获取设备信息做了点添加,如有不足、错误之处,希望大家多多指点,多多包涵,一起学习,一起进步。
这里主要是获取设备管理器里的设备名称、设备ID、供应商、是否安装驱动等信息
主要是是两个类一个是DeviceClasses 类,这个类用来获取设备的类型和设备类型的图标。内容和网上的一样未变动,只是加上了点注释。///<summary> /// 设备类型 /// </summary> public class DeviceClasses { public static Guid ClassesGuid; public const int MAX_SIZE_DEVICE_DESCRIPTION = 1000; public const int CR_SUCCESS = 0x00000000; public const int CR_NO_SUCH_VALUE = 0x00000025; public const int CR_INVALID_DATA = 0x0000001F; private const int DIGCF_PRESENT = 0x00000002; private const int DIOCR_INSTALLER = 0x00000001; private const int MAXIMUM_ALLOWED = 0x02000000; public const int DMI_MASK = 0x00000001; public const int DMI_BKCOLOR = 0x00000002; public const int DMI_USERECT = 0x00000004; /// <summary> /// 定义了一个设备实例就是一个设备信息集合的成员 /// </summary> [StructLayout(LayoutKind.Sequential)] class SP_DEVINFO_DATA { public int cbSize; public Guid ClassGuid; public int DevInst; public ulong Reserved; } /// <summary> /// 提供每个类的GUID枚举本地机器安装的设备类 /// </summary> /// <param name="ClassIndex"></param> /// <param name="ClassGuid"></param> /// <param name="Params"></param> /// <returns></returns> [DllImport("cfgmgr32.dll")] private static extern UInt32 CM_Enumerate_Classes(UInt32 ClassIndex, ref Guid ClassGuid, UInt32 Params); /// <summary> /// 检索与类GUID相关联的类名 /// </summary> /// <param name="ClassGuid"></param> /// <param name="ClassName"></param> /// <param name="ClassNameSize"></param> /// <param name="RequiredSize"></param> /// <returns></returns> [DllImport("setupapi.dll")] private static extern Boolean SetupDiClassNameFromGuidA(ref Guid ClassGuid, StringBuilder ClassName, UInt32 ClassNameSize, ref UInt32 RequiredSize); /// <summary> /// 获取一个指定类别或全部类别的所有已安装设备的信息 /// </summary> /// <param name="ClassGuid"></param> /// <param name="Enumerator"></param> /// <param name="hwndParent"></param> /// <param name="Flags"></param> /// <returns></returns> [DllImport("setupapi.dll")] private static extern IntPtr SetupDiGetClassDevsA(ref Guid ClassGuid, UInt32 Enumerator, IntPtr hwndParent, UInt32 Flags); /// <summary> /// 销毁一个设备信息集合,并且释放所有关联的内存 /// </summary> /// <param name="DeviceInfoSet"></param> /// <returns></returns> [DllImport("setupapi.dll")] private static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); /// <summary> /// 打开设备安装程序类的注册表项,设备接口类的注册表项,或一个特定类的子项。此函数打开本地计算机或远程计算机上指定的键。 /// </summary> /// <param name="ClassGuid"></param> /// <param name="samDesired"></param> /// <param name="Flags"></param> /// <param name="MachineName"></param> /// <param name="Reserved"></param> /// <returns></returns> [DllImport("setupapi.dll")] private static extern IntPtr SetupDiOpenClassRegKeyExA(ref Guid ClassGuid, UInt32 samDesired, int Flags, IntPtr MachineName, UInt32 Reserved); /// <summary> /// 获取设备信息集合的设备信息元素。 /// </summary> /// <param name="DeviceInfoSet"></param> /// <param name="MemberIndex"></param> /// <param name="DeviceInfoData"></param> /// <returns></returns> [DllImport("setupapi.dll")] private static extern Boolean SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, UInt32 MemberIndex, SP_DEVINFO_DATA DeviceInfoData); /// <summary> /// 取得指定项或子项的默认(未命名)值 /// </summary> /// <param name="KeyClass"></param> /// <param name="SubKey"></param> /// <param name="ClassDescription"></param> /// <param name="sizeB"></param> /// <returns></returns> [DllImport("advapi32.dll")] private static extern UInt32 RegQueryValueA(IntPtr KeyClass, UInt32 SubKey, StringBuilder ClassDescription, ref UInt32 sizeB); /// <summary> /// 设备类型图标信息 /// </summary> [StructLayout(LayoutKind.Sequential)] public class SP_CLASSIMAGELIST_DATA { public int cbSize; public string ImageList; public ulong Reserved; } public struct RECT { long left; long top; long right; long bottom; } /// <summary> /// 载入图片 /// </summary> /// <param name="hInstance"></param> /// <param name="Reserved"></param> /// <returns></returns> [DllImport("user32.dll")] public static extern int LoadBitmapW(int hInstance, ulong Reserved); /// <summary> /// 获取图标 /// </summary> /// <param name="ClassImageListData"></param> /// <returns></returns> [DllImport("setupapi.dll")] public static extern Boolean SetupDiGetClassImageList(out SP_CLASSIMAGELIST_DATA ClassImageListData); /// <summary> /// 绘制小图标 /// </summary> /// <param name="hdc"></param> /// <param name="rc"></param> /// <param name="MiniIconIndex"></param> /// <param name="Flags"></param> /// <returns></returns> [DllImport("setupapi.dll")] public static extern int SetupDiDrawMiniIcon(Graphics hdc, RECT rc, int MiniIconIndex, int Flags); /// <summary> /// 检索指定类提供的小图标的索引。 /// </summary> /// <param name="ClassGuid"></param> /// <param name="MiniIconIndex"></param> /// <returns></returns> [DllImport("setupapi.dll")] public static extern bool SetupDiGetClassBitmapIndex(Guid ClassGuid, out int MiniIconIndex); /// <summary> /// 加载小图标 /// </summary> /// <param name="classGuid"></param> /// <param name="hIcon"></param> /// <param name="index"></param> /// <returns></returns> [DllImport("setupapi.dll")] public static extern int SetupDiLoadClassIcon(ref Guid classGuid, out IntPtr hIcon, out int index); /// <summary> /// 枚举设备类型 /// </summary> /// <param name="ClassIndex"></param> /// <param name="ClassName">设备类型名称</param> /// <param name="ClassDescription">设备类型说明</param> /// <param name="DevicePresent"></param> /// <returns></returns> public static int EnumerateClasses(UInt32 ClassIndex, StringBuilder ClassName, StringBuilder ClassDescription, ref bool DevicePresent) { Guid ClassGuid = Guid.Empty; IntPtr NewDeviceInfoSet; UInt32 result; SP_DEVINFO_DATA DeviceInfoData = new SP_DEVINFO_DATA(); bool resNam = false; UInt32 RequiredSize = 0; result = CM_Enumerate_Classes(ClassIndex, ref ClassGuid, 0); DevicePresent = false; SP_CLASSIMAGELIST_DATA imagelist = new SP_CLASSIMAGELIST_DATA(); if (result != CR_SUCCESS) { return (int)result; } resNam = SetupDiClassNameFromGuidA(ref ClassGuid, ClassName, RequiredSize, ref RequiredSize); if (RequiredSize > 0) { ClassName.Capacity = (int)RequiredSize; resNam = SetupDiClassNameFromGuidA(ref ClassGuid, ClassName, RequiredSize, ref RequiredSize); } NewDeviceInfoSet = SetupDiGetClassDevsA(ref ClassGuid, 0, IntPtr.Zero, DIGCF_PRESENT); if (NewDeviceInfoSet.ToInt32() == -1) { DevicePresent = false; return 0; } UInt32 numD = 0; DeviceInfoData.cbSize = 28; DeviceInfoData.DevInst = 0; DeviceInfoData.ClassGuid = System.Guid.Empty; DeviceInfoData.Reserved = 0; Boolean res1 = SetupDiEnumDeviceInfo( NewDeviceInfoSet, numD, DeviceInfoData); if (!res1) { DevicePresent = false; return 0; } SetupDiDestroyDeviceInfoList(NewDeviceInfoSet); IntPtr KeyClass = SetupDiOpenClassRegKeyExA( ref ClassGuid, MAXIMUM_ALLOWED, DIOCR_INSTALLER, IntPtr.Zero, 0); if (KeyClass.ToInt32() == -1) { DevicePresent = false; return 0; } UInt32 sizeB = MAX_SIZE_DEVICE_DESCRIPTION; ClassDescription.Capacity = MAX_SIZE_DEVICE_DESCRIPTION; UInt32 res = RegQueryValueA(KeyClass, 0, ClassDescription, ref sizeB); if (res != 0) ClassDescription = new StringBuilder(""); //No device description DevicePresent = true; ClassesGuid = DeviceInfoData.ClassGuid; return 0; } }
然后是DeviceInfo类,这个类用来获取设备详细信息。里面改为了获取设备ID、供应商、是否安装驱动这个三个数据,然后就是加了个获取其它(未知)设备类型信息的函数,里面的其它(未知)设备判断处理 不是很好,但是工作赶时间,暂时先这样写了。
///<summary> /// 设备详细 /// </summary> public class DeviceInfo { private const int DIGCF_ALLCLASSES = (0x00000004); private const int DIGCF_PRESENT = (0x00000002); private const int MAX_DEV_LEN = 1000;//返回值最大长度 private const int SPDRP_DEVICEDESC = (0x00000000);// DeviceDesc (R/W) private const int SPDRP_HARDWAREID = (0x00000001);// HardwareID (R/W) private const int SPDRP_COMPATIBLEIDS = (0x00000002);// CompatibleIDs (R/W) private const int SPDRP_UNUSED0 = (0x00000003);// unused private const int SPDRP_SERVICE = (0x00000004);// Service (R/W) private const int SPDRP_UNUSED1 = (0x00000005);// unused private const int SPDRP_UNUSED2 = (0x00000006);// unused private const int SPDRP_CLASS = (0x00000007);// Class (R--tied to ClassGUID) private const int SPDRP_CLASSGUID = (0x00000008);// ClassGUID (R/W) private const int SPDRP_DRIVER = (0x00000009);// Driver (R/W) private const int SPDRP_CONFIGFLAGS = (0x0000000A);// ConfigFlags (R/W) private const int SPDRP_MFG = (0x0000000B);// Mfg (R/W) private const int SPDRP_FRIENDLYNAME = (0x0000000C);// FriendlyName (R/W) private const int SPDRP_LOCATION_INFORMATION = (0x0000000D);// LocationInformation (R/W) private const int SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = (0x0000000E);// PhysicalDeviceObjectName (R) private const int SPDRP_CAPABILITIES = (0x0000000F);// Capabilities (R) private const int SPDRP_UI_NUMBER = (0x00000010);// UiNumber (R) private const int SPDRP_UPPERFILTERS = (0x00000011);// UpperFilters (R/W) private const int SPDRP_LOWERFILTERS = (0x00000012);// LowerFilters (R/W) private const int SPDRP_BUSTYPEGUID = (0x00000013);// BusTypeGUID (R) private const int SPDRP_LEGACYBUSTYPE = (0x00000014);// LegacyBusType (R) private const int SPDRP_BUSNUMBER = (0x00000015);// BusNumber (R) private const int SPDRP_ENUMERATOR_NAME = (0x00000016);// Enumerator Name (R) private const int SPDRP_SECURITY = (0x00000017);// Security (R/W, binary form) private const int SPDRP_SECURITY_SDS = (0x00000018);// Security=(W, SDS form) private const int SPDRP_DEVTYPE = (0x00000019);// Device Type (R/W) private const int SPDRP_EXCLUSIVE = (0x0000001A);// Device is exclusive-access (R/W) private const int SPDRP_CHARACTERISTICS = (0x0000001B);// Device Characteristics (R/W) private const int SPDRP_ADDRESS = (0x0000001C);// Device Address (R) private const int SPDRP_UI_NUMBER_DESC_FORMAT = (0X0000001D);// UiNumberDescFormat (R/W) private const int SPDRP_DEVICE_POWER_DATA = (0x0000001E);// Device Power Data (R) private const int SPDRP_REMOVAL_POLICY = (0x0000001F);// Removal Policy (R) private const int SPDRP_REMOVAL_POLICY_HW_DEFAULT = (0x00000020);// Hardware Removal Policy (R) private const int SPDRP_REMOVAL_POLICY_OVERRIDE = (0x00000021);// Removal Policy Override (RW) private const int SPDRP_INSTALL_STATE = (0x00000022);// Device Install State (R) private const int SPDRP_LOCATION_PATHS = (0x00000023);// Device Location Paths (R) private const int SPDRP_BASE_CONTAINERID = (0x00000024);// Base ContainerID (R) private const int SPDRP_MAXIMUM_PROPERTY = (0x00000025);// Upper bound on ordinals [StructLayout(LayoutKind.Sequential)] private class SP_DEVINFO_DATA { public int cbSize; public Guid ClassGuid; public int DevInst; public ulong Reserved; }; [DllImport("setupapi.dll")] private static extern Boolean SetupDiClassGuidsFromNameA(string ClassN, ref Guid guids, UInt32 ClassNameSize, ref UInt32 ReqSize); [DllImport("setupapi.dll")] private static extern IntPtr SetupDiGetClassDevsA(ref Guid ClassGuid, UInt32 Enumerator, IntPtr hwndParent, UInt32 Flags); [DllImport("setupapi.dll")] private static extern Boolean SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, UInt32 MemberIndex, SP_DEVINFO_DATA DeviceInfoData); [DllImport("setupapi.dll")] private static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet); [DllImport("setupapi.dll")] private static extern Boolean SetupDiGetDeviceRegistryPropertyA(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, UInt32 Property, UInt32 PropertyRegDataType, StringBuilder PropertyBuffer, UInt32 PropertyBufferSize, IntPtr RequiredSize); /// <summary> /// 通过设备类型枚举设备信息 /// </summary> /// <param name="DeviceIndex"></param> /// <param name="ClassName"></param> /// <param name="DeviceName"></param> /// <returns></returns> public static int EnumerateDevices(UInt32 DeviceIndex, string ClassName, StringBuilder DeviceName, StringBuilder DeviceID, StringBuilder Mfg, StringBuilder IsInstallDrivers) { UInt32 RequiredSize = 0; Guid guid = Guid.Empty; Guid[] guids = new Guid[1]; IntPtr NewDeviceInfoSet; SP_DEVINFO_DATA DeviceInfoData = new SP_DEVINFO_DATA(); bool res = SetupDiClassGuidsFromNameA(ClassName, ref guids[0], RequiredSize, ref RequiredSize); if (RequiredSize == 0) { //类型不正确 DeviceName = new StringBuilder(""); return -2; } if (!res) { guids = new Guid[RequiredSize]; res = SetupDiClassGuidsFromNameA(ClassName, ref guids[0], RequiredSize, ref RequiredSize); if (!res || RequiredSize == 0) { //类型不正确 DeviceName = new StringBuilder(""); return -2; } } //通过类型获取设备信息 NewDeviceInfoSet = SetupDiGetClassDevsA(ref guids[0], 0, IntPtr.Zero, DIGCF_PRESENT); if (NewDeviceInfoSet.ToInt32() == -1) { //设备不可用 DeviceName = new StringBuilder(""); return -3; } DeviceInfoData.cbSize = 28; //正常状态 DeviceInfoData.DevInst = 0; DeviceInfoData.ClassGuid = System.Guid.Empty; DeviceInfoData.Reserved = 0; res = SetupDiEnumDeviceInfo(NewDeviceInfoSet, DeviceIndex, DeviceInfoData); if (!res) { //没有设备 SetupDiDestroyDeviceInfoList(NewDeviceInfoSet); DeviceName = new StringBuilder(""); return -1; } DeviceName.Capacity = MAX_DEV_LEN; DeviceID.Capacity = MAX_DEV_LEN; Mfg.Capacity = MAX_DEV_LEN; IsInstallDrivers.Capacity = MAX_DEV_LEN; if (!SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet, DeviceInfoData, SPDRP_FRIENDLYNAME, 0, DeviceName, MAX_DEV_LEN, IntPtr.Zero)) { res = SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet, DeviceInfoData, SPDRP_DEVICEDESC, 0, DeviceName, MAX_DEV_LEN, IntPtr.Zero); if (!res) { //类型不正确 SetupDiDestroyDeviceInfoList(NewDeviceInfoSet); DeviceName = new StringBuilder(""); return -4; } } //设备ID bool resHardwareID = SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet, DeviceInfoData, SPDRP_HARDWAREID, 0, DeviceID, MAX_DEV_LEN, IntPtr.Zero); if (!resHardwareID) { //设备ID未知 DeviceID = new StringBuilder(""); DeviceID.Append("未知"); } //设备供应商 bool resMfg = SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet, DeviceInfoData, SPDRP_MFG, 0, Mfg, MAX_DEV_LEN, IntPtr.Zero); if (!resMfg) { //设备供应商未知 Mfg = new StringBuilder(""); Mfg.Append("未知"); } //设备是否安装驱动 bool resIsInstallDrivers = SetupDiGetDeviceRegistryPropertyA(NewDeviceInfoSet, DeviceInfoData, SPDRP_DRIVER, 0, IsInstallDrivers, MAX_DEV_LEN, IntPtr.Zero); if (!resIsInstallDrivers) { //设备是否安装驱动 IsInstallDrivers = new StringBuilder(""); } //释放当前设备占用内存 SetupDiDestroyDeviceInfoList(NewDeviceInfoSet); return 0; } /// <summary> /// 获取未知设备信息 /// </summary> /// <param name="DeviceIndex"></param> /// <param name="ClassName"></param> /// <param name="DeviceName"></param> /// <returns></returns> public static int EnumerateDevices(List<string> NameList, List<string> IDList, List<string> MfgList, List<string> TypeList, List<string> IsInstallDriversList) { Guid myGUID = System.Guid.Empty; IntPtr hDevInfo = SetupDiGetClassDevsA(ref myGUID, 0, IntPtr.Zero, DIGCF_ALLCLASSES); if (hDevInfo.ToInt32() == -1) { //设备不可用 return -3; } SP_DEVINFO_DATA DeviceInfoData = new SP_DEVINFO_DATA(); DeviceInfoData.cbSize = 28; //正常状态 DeviceInfoData.DevInst = 0; DeviceInfoData.ClassGuid = System.Guid.Empty; DeviceInfoData.Reserved = 0; UInt32 i; for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++) { //设备名称 StringBuilder DeviceName = new StringBuilder(""); //设备ID StringBuilder DeviceID = new StringBuilder(""); //设备供应商 StringBuilder Mfg = new StringBuilder(""); //设备类型 StringBuilder DeviceType = new StringBuilder(""); //设备类型 StringBuilder IsInstallDrivers = new StringBuilder(""); DeviceName.Capacity = MAX_DEV_LEN; DeviceID.Capacity = MAX_DEV_LEN; DeviceType.Capacity = MAX_DEV_LEN; Mfg.Capacity = MAX_DEV_LEN; IsInstallDrivers.Capacity = MAX_DEV_LEN; bool resName = SetupDiGetDeviceRegistryPropertyA(hDevInfo, DeviceInfoData, SPDRP_DEVICEDESC, 0, DeviceName, MAX_DEV_LEN, IntPtr.Zero); if (!resName) { //设备名称未知 DeviceName = new StringBuilder(""); } bool resClass = SetupDiGetDeviceRegistryPropertyA(hDevInfo, DeviceInfoData, SPDRP_CLASS, 0, DeviceType, MAX_DEV_LEN, IntPtr.Zero); if (!resClass) { //设备类型未知 DeviceType = new StringBuilder(""); } //设备ID bool resHardwareID = SetupDiGetDeviceRegistryPropertyA(hDevInfo, DeviceInfoData, SPDRP_HARDWAREID, 0, DeviceID, MAX_DEV_LEN, IntPtr.Zero); if (!resHardwareID) { //设备ID未知 DeviceID = new StringBuilder(""); } //设备供应商 bool resMfg = SetupDiGetDeviceRegistryPropertyA(hDevInfo, DeviceInfoData, SPDRP_MFG, 0, Mfg, MAX_DEV_LEN, IntPtr.Zero); if (!resMfg) { //设备供应商未知 Mfg = new StringBuilder(""); } bool resIsInstallDrivers = SetupDiGetDeviceRegistryPropertyA(hDevInfo, DeviceInfoData, SPDRP_DRIVER, 0, IsInstallDrivers, MAX_DEV_LEN, IntPtr.Zero); if (!resIsInstallDrivers) { //设备是否安装驱动 IsInstallDrivers = new StringBuilder(""); } if (string.IsNullOrEmpty(DeviceType.ToString())) { if (!string.IsNullOrEmpty(DeviceName.ToString()) && !string.IsNullOrEmpty(DeviceID.ToString())) { TypeList.Add("其它设备"); NameList.Add(DeviceName.ToString()); IDList.Add(DeviceID.ToString()); MfgList.Add(Mfg.ToString()); IsInstallDriversList.Add(IsInstallDrivers.ToString()); } } } //释放当前设备占用内存 SetupDiDestroyDeviceInfoList(hDevInfo); return 0; } }