您的位置:首页 > 产品设计 > UI/UE

C#:结合设备安装类GUID和设备接口类GUID获取设备VIDPID

2011-09-10 18:58 435 查看
前言:

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:splashcn@msn.com
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;    // 产品编号
}

/// <summary>
/// 基于WDK获取系统设备的VIDPID
/// </summary>
public partial class USB
{
/// <summary>
/// 获取系统所有设备的VIDPID
/// </summary>
public static HIDD_VIDPID[] AllVidPid
{
get
{
return WhoVidPid(Guid.Empty, Guid.Empty);
}
}

/// <summary>
/// 结合设备安装类GUID和设备接口类GUID获取设备VIDPID
/// </summary>
/// <param name="setupClassGuid">设备安装类GUID,Empty忽视</param>
/// <param name="interfaceClassGuid">设备接口类GUID,Empty忽视</param>
/// <returns>设备VIDPID列表</returns>
/// <remarks>
/// 优点:直接通过设备实例ID提取VIDPID,从而无需获取设备路径来读写IO
/// </remarks>
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<HIDD_VIDPID> DeviceList = new List<HIDD_VIDPID>();

// 存储设备实例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();
}

/// <summary>
/// 从搜索列表中提取出存在于系统中的VIDPID
/// </summary>
/// <param name="searchList">搜索列表</param>
/// <returns>系统中存在的VIDPID列表</returns>
public static HIDD_VIDPID[] WhoVidPid(HIDD_VIDPID[] searchList)
{
// 获取系统所有设备的VIDPID集合
HIDD_VIDPID[] DeviceCollection = AllVidPid;
if (DeviceCollection == null) return null;

List<HIDD_VIDPID> ValidList = new List<HIDD_VIDPID>();
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:splashcn@msn.com
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
{
/// <summary>
/// SetupApi.dll的PInvoke
/// </summary>
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
}
}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息