枚举设备管理器设备
技术关键是:
调用SetupDiGetClassDevs获取系统设备信息集合(Device Information Set),然后调用SetupDiEnumDeviceInfo枚举出集合中的每一个设备。设备信息集合是一个未文档化的结构体,用句柄HDEVINFO表示;集合内的每个设备成员,以结构体SP_DEVINFO_DATA描述,则是个文档化结构体;此外,设备成员内部还包含多个设备接口,以SP_DEVICE_INTERFACE_DATA描述。
首先是一些定义:
public static int INVALID_HANDLE_VALUE = -1;
public static int SPDRP_DEVICEDESC = (0x00000000);
public static uint DIF_REGISTERDEVICE = (0x00000019);
public static uint DIF_REMOVE = (0x00000005);
public static uint DICD_GENERATE_ID = (0x00000001);
public static uint DIGCF_ALLCLASSES = (0x00000004);
public static uint DIGCF_PRESENT = (0x00000002);
public static int MAX_DEV_LEN = 1000;
public static uint ERROR_INSUFFICIENT_BUFFER = (0x0000007A);
public static uint INSTALLFLAG_FORCE = (0x00000001);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SP_DEVINFO_DATA
{
public int cbSize; //Size of the structure, in bytes.
public Guid ClassGuid; //GUID of the device interface class
public IntPtr DevInst; //Handle to this device instance
public IntPtr Reserved; //Reserved; do not use.
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct GUID
{
public uint Data1;
public ushort Data2;
public ushort Data3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data4;
}
函数的定义:
/// 获取一个指定类别或全部类别的所有已安装设备的信息
[DllImport("setupapi.dll", SetLastError = true)]
public static extern IntPtr SetupDiGetClassDevs(
ref Guid ClassGuid,
UInt32 Enumerator,
IntPtr hParent,
UInt32 nFlags);
// 枚举指定设备信息集合的成员,并将数据放在SP_DEVINFO_DATA中
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiEnumDeviceInfo(
IntPtr DeviceInfoSet,
UInt32 dwIndex,
ref DriverEntity.SP_DEVINFO_DATA devInfoData);
// 获取指定设备的属性
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiGetDeviceRegistryProperty(
IntPtr lpInfoSet,
ref DriverEntity.SP_DEVINFO_DATA DeviceInfoData,
int Property,
UInt32 PropertyRegDataType,
StringBuilder PropertyBuffer,
Int32 PropertyBufferSize,
IntPtr RequiredSize);
错误信息:
[DllImport("kernel32.dll")]
public static extern UInt32 GetLastError();
源码:
public bool FindExistedDevice(string harewareID)
{
IntPtr DeviceInfoSet;
bool FOUND = false;
List<string> HWList = new List<string>();
DriverEntity.SP_DEVINFO_DATA DeviceInfoDate;
// DriverEntity.GUID guid = new DriverEntity.GUID();
Guid myGUID = System.Guid.Empty;
//创建一个当前所有设备集合
DeviceInfoSet = DriverDAL.SetupDiGetClassDevs(
ref myGUID,
0,
IntPtr.Zero,
DriverEntity.DIGCF_ALLCLASSES | DriverEntity.DIGCF_PRESENT);
if (DeviceInfoSet.ToInt32() == DriverEntity.INVALID_HANDLE_VALUE)
{
throw new Exception("GetClassDevs(All Present Devices)");
}
DeviceInfoDate = new DriverEntity.SP_DEVINFO_DATA();
DeviceInfoDate.cbSize = Marshal.SizeOf(typeof(DriverEntity.SP_DEVINFO_DATA));
//枚举所有设备
UInt32 i;
StringBuilder buffer = new StringBuilder("");
buffer.Capacity = (Int32)DriverEntity.MAX_DEV_LEN;
for (i = 0; DriverDAL.SetupDiEnumDeviceInfo(DeviceInfoSet, i, ref DeviceInfoDate);i++ )
{
while (!DriverDAL.SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
ref DeviceInfoDate,
DriverEntity.SPDRP_DEVICEDESC,
0,
buffer,
DriverEntity.MAX_DEV_LEN,
IntPtr.Zero))
{
if (DriverDAL.GetLastError() == DriverEntity.ERROR_INSUFFICIENT_BUFFER)
{
throw new Exception("Buffer size is not enough");
}
}
HWList.Add(buffer.ToString());
}
Console.Write(DriverDAL.GetLastError());
foreach( String item in HWList)
{
if (String.Equals(item,harewareID))
{
FOUND = true;
break;
}
}
return FOUND;
}