VID和PID常被用于厂家的软件加密,只有在系统中检测到某VID和PID的设备时,软件才能运行。因此获取某一类型设备或者全部设备的VID和PID集合至关重要。获取设备VID和PID的一般流程是通过设备接口类GUID创建设备信息集,然后从设备接口详细信息中获取设备路径,再调用HidD_GetAttributes从属性中读取VID和PID。该方法的缺点是需要事先知道设备接口类GUID,且每次只能获取一个设备接口类的VID和PID集合。本方法既可以指定设备安装类GUID和/或设备接口类GUID,也可以两者都不指定而直接创建设备信息集,然后通过设备信息数据获取设备实例ID,并直接从设备实例ID中提取出VID和PID,巧妙地避开了对设备IO的读写。
下载:
WDK_VidPidQuery.zip
源代码:
WDKVidPidQuery.cs
/* ----------------------------------------------------------
文件名称:WDKVidPidQuery.cs
作者:秦建辉
MSN:[email protected]
QQ:36748897
博客:http://blog.csdn.net/jhqin
开发环境:
Visual Studio V2010
.NET Framework 4 Client Profile
版本历史:
V1.0 2011年09月10日
结合设备安装类GUID和设备接口类GUID获取设备VIDPID
------------------------------------------------------------ */
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace Splash.IO.PORTS
{
public struct HIDD_VIDPID
{
public UInt16 VendorID; // 供应商标识
public UInt16 ProductID; // 产品编号
}
///
/// 基于WDK获取系统设备的VIDPID
///
public partial class USB
{
///
/// 获取系统所有设备的VIDPID
///
public static HIDD_VIDPID[] AllVidPid
{
get
{
return WhoVidPid(Guid.Empty, Guid.Empty);
}
}
///
/// 结合设备安装类GUID和设备接口类GUID获取设备VIDPID
///
/// 设备安装类GUID,Empty忽视
/// 设备接口类GUID,Empty忽视
/// 设备VIDPID列表
///
/// 优点:直接通过设备实例ID提取VIDPID,从而无需获取设备路径来读写IO
///
public static HIDD_VIDPID[] WhoVidPid(Guid setupClassGuid, Guid interfaceClassGuid, String Enumerator = null)
{
// 根据设备安装类GUID创建空的设备信息集合
IntPtr DeviceInfoSet;
if (setupClassGuid == Guid.Empty)
{
DeviceInfoSet = SetupDiCreateDeviceInfoList(IntPtr.Zero, IntPtr.Zero);
}
else
{
DeviceInfoSet = SetupDiCreateDeviceInfoList(ref setupClassGuid, IntPtr.Zero);
}
if (DeviceInfoSet == new IntPtr(-1)) return null;
// 根据设备接口类GUID创建新的设备信息集合
IntPtr hDevInfo;
if (interfaceClassGuid == Guid.Empty)
{
hDevInfo = SetupDiGetClassDevsEx(
IntPtr.Zero,
Enumerator,
IntPtr.Zero,
DIGCF.DIGCF_ALLCLASSES | DIGCF.DIGCF_DEVICEINTERFACE | DIGCF.DIGCF_PRESENT,
DeviceInfoSet,
null,
IntPtr.Zero);
}
else
{
hDevInfo = SetupDiGetClassDevsEx(
ref interfaceClassGuid,
null,
IntPtr.Zero,
DIGCF.DIGCF_DEVICEINTERFACE | DIGCF.DIGCF_PRESENT,
DeviceInfoSet,
null,
IntPtr.Zero);
}
if (hDevInfo == new IntPtr(-1)) return null;
// 枚举所有设备
List DeviceList = new List();
// 存储设备实例ID
StringBuilder DeviceInstanceId = new StringBuilder(256);
// 获取设备信息数据
UInt32 DeviceIndex = 0;
SP_DEVINFO_DATA DeviceInfoData = SP_DEVINFO_DATA.Empty;
while (SetupDiEnumDeviceInfo(hDevInfo, DeviceIndex++, ref DeviceInfoData))
{ // 获取设备实例ID
if (SetupDiGetDeviceInstanceId(hDevInfo, ref DeviceInfoData, DeviceInstanceId, DeviceInstanceId.Capacity, IntPtr.Zero))
{
String PNPDeviceID = DeviceInstanceId.ToString();
Match match = Regex.Match(PNPDeviceID, "VID_[0-9|A-F]{4}&PID_[0-9|A-F]{4}");
if (match.Success)
{
HIDD_VIDPID Entity;
Entity.VendorID = Convert.ToUInt16(match.Value.Substring(4, 4), 16); // 供应商标识
Entity.ProductID = Convert.ToUInt16(match.Value.Substring(13, 4), 16); // 产品编号
if (!DeviceList.Contains(Entity))
DeviceList.Add(Entity);
}
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
if (DeviceList.Count == 0)
return null;
else
return DeviceList.ToArray();
}
///
/// 从搜索列表中提取出存在于系统中的VIDPID
///
/// 搜索列表
/// 系统中存在的VIDPID列表
public static HIDD_VIDPID[] WhoVidPid(HIDD_VIDPID[] searchList)
{
// 获取系统所有设备的VIDPID集合
HIDD_VIDPID[] DeviceCollection = AllVidPid;
if (DeviceCollection == null) return null;
List ValidList = new List();
foreach (HIDD_VIDPID VidPid in searchList)
{
if (Array.IndexOf(DeviceCollection, VidPid) != -1)
{
ValidList.Add(VidPid);
}
}
if (ValidList.Count == 0)
return null;
else
return ValidList.ToArray();
}
}
}
SetupApi.cs
/* ----------------------------------------------------------
文件名称:SetupApi.cs
作者:秦建辉
MSN:[email protected]
QQ:36748897
博客:http://blog.csdn.net/jhqin
开发环境:
Visual Studio V2010
.NET Framework 4 Client Profile
版本历史:
V1.0 2011年09月05日
实现对setupapi.dll接口的PInvoke
参考资料:
http://www.pinvoke.net/
------------------------------------------------------------ */
using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Splash.IO.PORTS
{
///
/// SetupApi.dll的PInvoke
///
public partial class USB
{
#region ENUM
[Flags]
private enum DIGCF
{
DIGCF_DEFAULT = 0x00000001,
DIGCF_PRESENT = 0x00000002,
DIGCF_ALLCLASSES = 0x00000004, // 设备安装类
DIGCF_PROFILE = 0x00000008,
DIGCF_DEVICEINTERFACE = 0x00000010, // 设备接口类
}
#endregion
#region STRUCT
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVINFO_DATA
{
public static readonly SP_DEVINFO_DATA Empty = new SP_DEVINFO_DATA(Marshal.SizeOf(typeof(SP_DEVINFO_DATA)));
public UInt32 cbSize;
public Guid ClassGuid;
public UInt32 DevInst;
public IntPtr Reserved;
private SP_DEVINFO_DATA(int size)
{
cbSize = (UInt32)size;
ClassGuid = Guid.Empty;
DevInst = 0;
Reserved = IntPtr.Zero;
}
}
[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVICE_INTERFACE_DATA
{
public static readonly SP_DEVICE_INTERFACE_DATA Empty = new SP_DEVICE_INTERFACE_DATA(Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA)));
public UInt32 cbSize;
public Guid InterfaceClassGuid;
public UInt32 Flags;
public UIntPtr Reserved;
private SP_DEVICE_INTERFACE_DATA(int size)
{
cbSize = (uint)size;
InterfaceClassGuid = Guid.Empty;
Flags = 0;
Reserved = UIntPtr.Zero;
}
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public UInt32 cbSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public String DevicePath;
}
#endregion
#region API
#region SetupDiGetClassDevs
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SetupDiGetClassDevs(
ref Guid ClassGuid,
[MarshalAs(UnmanagedType.LPTStr)] String Enumerator,
IntPtr hwndParent,
DIGCF Flags
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SetupDiGetClassDevs(
IntPtr ClassGuid, // null
String Enumerator,
IntPtr hwndParent,
DIGCF Flags
);
#endregion
#region SetupDiGetClassDevsEx
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SetupDiGetClassDevsEx(
ref Guid ClassGuid,
[MarshalAs(UnmanagedType.LPTStr)] String Enumerator,
IntPtr hwndParent,
DIGCF Flags,
IntPtr DeviceInfoSet,
[MarshalAs(UnmanagedType.LPTStr)] String MachineName,
IntPtr Reserved
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SetupDiGetClassDevsEx(
IntPtr ClassGuid,
[MarshalAs(UnmanagedType.LPTStr)] String Enumerator,
IntPtr hwndParent,
DIGCF Flags,
IntPtr DeviceInfoSet,
[MarshalAs(UnmanagedType.LPTStr)] String MachineName,
IntPtr Reserved
);
#endregion
#region SetupDiEnumDeviceInterfaces
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiEnumDeviceInterfaces(
IntPtr hDevInfo,
ref SP_DEVINFO_DATA devInfo,
ref Guid interfaceClassGuid,
UInt32 memberIndex,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiEnumDeviceInterfaces(
IntPtr hDevInfo,
[MarshalAs(UnmanagedType.AsAny)] Object devInfo,
ref Guid interfaceClassGuid,
UInt32 memberIndex,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData
);
#endregion
#region SetupDiGetDeviceInterfaceDetail
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiGetDeviceInterfaceDetail(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
Int32 deviceInterfaceDetailDataSize,
out Int32 requiredSize,
ref SP_DEVINFO_DATA deviceInfoData
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiGetDeviceInterfaceDetail(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
Int32 deviceInterfaceDetailDataSize,
out Int32 requiredSize,
[MarshalAs(UnmanagedType.AsAny)] object deviceInfoData // null
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiGetDeviceInterfaceDetail(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
Int32 deviceInterfaceDetailDataSize,
IntPtr requiredSize, // null
[MarshalAs(UnmanagedType.AsAny)] object deviceInfoData // null
);
#endregion
#region SetupDiCreateDeviceInfoList
[DllImport("setupapi.dll", SetLastError = true)]
private static extern IntPtr SetupDiCreateDeviceInfoList(ref Guid ClassGuid, IntPtr hwndParent);
[DllImport("setupapi.dll", SetLastError = true)]
private static extern IntPtr SetupDiCreateDeviceInfoList(IntPtr ClassGuid, IntPtr hwndParent);
#endregion
[DllImport("setupapi.dll", SetLastError = true)]
private static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport("setupapi.dll", SetLastError = true)]
private static extern Boolean SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, UInt32 MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);
#region SetupDiGetDeviceInstanceId
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiGetDeviceInstanceId(
IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
StringBuilder DeviceInstanceId,
Int32 DeviceInstanceIdSize,
out Int32 RequiredSize
);
[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern Boolean SetupDiGetDeviceInstanceId(
IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
StringBuilder DeviceInstanceId,
Int32 DeviceInstanceIdSize,
IntPtr RequiredSize
);
#endregion
#endregion
}
}