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

前言:

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
    }
}

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值