none
Enumerate Human Interface Devices RRS feed

  • Question

  • I am trying to figure out how to retrieve the list of devices that shows up in the Device Manager under Human Interface Devices. I would like to be able to look at the properties of each device as well. For example, lets say I am looking at a USB Input Device. I would like to be able to determine the Device Description, Hardware Ids, and Manufacturer. You can get to these values by double clicking a device under Human Interface Devices and going to the Details tab.

    Does anyone know how I can enumerate these objects and look at their properties? Thanks in advance.

    Tuesday, March 15, 2011 1:20 PM

Answers

  • Thanks Seabass. That was helpful. I found more good info in this codeplex project .

    With that, I was able to come up with the following method.

    public static string EnumerateHids()
    {
      StringBuilder details = new StringBuilder();
      HIDImports.HIDD_ATTRIBUTES deviceAttributes;
      Guid guid;
      uint index = 0;
    
      // get the GUID of the HID class
      HIDImports.HidD_GetHidGuid(out guid);
    
      // get a handle to all devices that are part of the HID class
      IntPtr hDevInfo = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, HIDImports.DIGCF_DEVICEINTERFACE);
    
      // create a new interface data struct and initialize its size
      HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
      diData.cbSize = Marshal.SizeOf(diData);
    
      // get a device interface to a single device (enumerate all devices)
      while (HIDImports.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, index, ref diData))
      {
        UInt32 size = 0;
    
        // get the buffer size for this device detail instance (returned in the size parameter)
        HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);
    
        // create a detail struct and set its size
        HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();
    
        //On Win x86, cbSize = 5, On x64, cbSize = 8 i
        diDetail.cbSize = (IntPtr.Size == 8) ? (uint)8 : (uint)5;
    
        // actually get the detail struct
        if (HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, ref diDetail, size, out size, IntPtr.Zero))
        {
          // open a read/write handle to our device using the DevicePath returned
          SafeHandle safeHandle = HIDImports.CreateFile(diDetail.DevicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero);
    
          // create an attributes struct and initialize the size
          deviceAttributes = new HIDImports.HIDD_ATTRIBUTES();
          deviceAttributes.Size = Marshal.SizeOf(deviceAttributes);
    
          // get the attributes of the current device
          if (HIDImports.HidD_GetAttributes(safeHandle.DangerousGetHandle(), ref deviceAttributes))
          {
            details.AppendLine("--- HID DEVICE FOUND ---");
            details.AppendLine(String.Format("ProductID: 0x{0}", deviceAttributes.ProductID.ToString("X4")));
            details.AppendLine(String.Format("VendorID: 0x{0}", deviceAttributes.VendorID.ToString("X4")));
            details.AppendLine(String.Format("VersionNumber: 0x{0}", deviceAttributes.VersionNumber.ToString("X4")));
            details.AppendLine(String.Format("Size: 0x{0}", deviceAttributes.Size.ToString("X4")));
            details.AppendLine();
          }
        }
        index++;
      }
    
      return details.ToString();
    }
    

    The method uses HIDImports.cs, whose content is below:

    //////////////////////////////////////////////////////////////////////////////////
    //	HIDImports.cs
    //	For more information: http://wiimotelib.codeplex.com/
    //////////////////////////////////////////////////////////////////////////////////
    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using Microsoft.Win32.SafeHandles;
    
    namespace CreateBinaryFromXml
    {
    	public class HIDImports
    	{
    		// Flags controlling what is included in the device information set built by SetupDiGetClassDevs
    	  internal const int DIGCF_DEFAULT = 0x00000001;       // only valid with DIGCF_DEVICEINTERFACE
        internal const int DIGCF_PRESENT = 0x00000002;
        internal const int DIGCF_ALLCLASSES = 0x00000004;
        internal const int DIGCF_PROFILE = 0x00000008;
        internal const int DIGCF_DEVICEINTERFACE = 0x00000010;
    
    		[Flags]
        internal enum EFileAttributes : uint
    		{
    		  Readonly     = 0x00000001,
    		  Hidden      = 0x00000002,
    		  System      = 0x00000004,
    		  Directory    = 0x00000010,
    		  Archive     = 0x00000020,
    		  Device      = 0x00000040,
    		  Normal      = 0x00000080,
    		  Temporary    = 0x00000100,
    		  SparseFile    = 0x00000200,
    		  ReparsePoint   = 0x00000400,
    		  Compressed    = 0x00000800,
    		  Offline     = 0x00001000,
    		  NotContentIndexed= 0x00002000,
    		  Encrypted    = 0x00004000,
    		  Write_Through  = 0x80000000,
    		  Overlapped    = 0x40000000,
    		  NoBuffering   = 0x20000000,
    		  RandomAccess   = 0x10000000,
    		  SequentialScan  = 0x08000000,
    		  DeleteOnClose  = 0x04000000,
    		  BackupSemantics = 0x02000000,
    		  PosixSemantics  = 0x01000000,
    		  OpenReparsePoint = 0x00200000,
    		  OpenNoRecall   = 0x00100000,
    		  FirstPipeInstance= 0x00080000
    		}
    
    		[StructLayout(LayoutKind.Sequential)]
        internal struct SP_DEVINFO_DATA
    		{
    			public uint cbSize;
    			public Guid ClassGuid;
    			public uint DevInst;
    			public IntPtr Reserved;
    		}
    
    		[StructLayout(LayoutKind.Sequential)]
        internal struct SP_DEVICE_INTERFACE_DATA
    		{
    			public int cbSize;
    			public Guid InterfaceClassGuid;
    			public int Flags;
    			public IntPtr RESERVED;
    		}
    
    		[StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
    		{
    			public UInt32 cbSize;
    			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    			public string DevicePath;
    		}
    
    		[StructLayout(LayoutKind.Sequential)]
    		public struct HIDD_ATTRIBUTES
    		{
    			public int Size;
    			public short VendorID;
    			public short ProductID;
    			public short VersionNumber;
    		}
    
    		[DllImport(@"hid.dll", CharSet=CharSet.Auto, SetLastError = true)]
        internal static extern void HidD_GetHidGuid(out Guid gHid);
    
    		[DllImport("hid.dll")]
        internal static extern Boolean HidD_GetAttributes(IntPtr HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);
    
    		[DllImport("hid.dll")]
        internal extern static bool HidD_SetOutputReport(
    			IntPtr HidDeviceObject,
    			byte[] lpReportBuffer,
    			uint ReportBufferLength);
    
    		[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern IntPtr SetupDiGetClassDevs(
    			ref Guid ClassGuid,
    			[MarshalAs(UnmanagedType.LPTStr)] string Enumerator,
    			IntPtr hwndParent,
    			UInt32 Flags
    			);
    
    		[DllImport(@"setupapi.dll", CharSet=CharSet.Auto, SetLastError = true)]
        internal static extern Boolean SetupDiEnumDeviceInterfaces(
    			IntPtr hDevInfo,
    			IntPtr devInvo,
    			ref Guid interfaceClassGuid,
    			UInt32 memberIndex,
    			ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData
    		);
    
    		[DllImport(@"setupapi.dll", SetLastError = true)]
        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(
    			IntPtr hDevInfo,
    			ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
    			IntPtr deviceInterfaceDetailData,
    			UInt32 deviceInterfaceDetailDataSize,
    			out UInt32 requiredSize,
    			IntPtr deviceInfoData
    		);
    
    		[DllImport(@"setupapi.dll", SetLastError = true)]
        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(
    			IntPtr hDevInfo,
    			ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
    			ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
    			UInt32 deviceInterfaceDetailDataSize,
    			out UInt32 requiredSize,
    			IntPtr deviceInfoData
    		);
    
    		[DllImport(@"setupapi.dll", CharSet=CharSet.Auto, SetLastError = true)]
        internal static extern UInt16 SetupDiDestroyDeviceInfoList(IntPtr hDevInfo);
    
    		[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern SafeFileHandle CreateFile(
    			string fileName,
    			[MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
    			[MarshalAs(UnmanagedType.U4)] FileShare fileShare,
    			IntPtr securityAttributes,
    			[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
    			[MarshalAs(UnmanagedType.U4)] EFileAttributes flags,
    			IntPtr template);
    
    			[DllImport("kernel32.dll", SetLastError=true)]
    			[return: MarshalAs(UnmanagedType.Bool)]
    			public static extern bool CloseHandle(IntPtr hObject);
    	}
    }
    
    

     

    • Marked as answer by BBauer42 Wednesday, March 16, 2011 12:19 PM
    Wednesday, March 16, 2011 12:18 PM

All replies

  • I believe this forum has the answers you are looking for.  Hope this helps.

    http://social.msdn.microsoft.com/forums/en-us/vcgeneral/thread/F9A2E2B3-88A0-4FD9-98FA-83FA4B94076D

    • Proposed as answer by Larcolais Gong Wednesday, March 16, 2011 2:13 AM
    • Unproposed as answer by BBauer42 Wednesday, March 16, 2011 12:19 PM
    Tuesday, March 15, 2011 1:51 PM
  • Any update? Has your question been resolved?

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, March 16, 2011 2:13 AM
  • Thanks Seabass. That was helpful. I found more good info in this codeplex project .

    With that, I was able to come up with the following method.

    public static string EnumerateHids()
    {
      StringBuilder details = new StringBuilder();
      HIDImports.HIDD_ATTRIBUTES deviceAttributes;
      Guid guid;
      uint index = 0;
    
      // get the GUID of the HID class
      HIDImports.HidD_GetHidGuid(out guid);
    
      // get a handle to all devices that are part of the HID class
      IntPtr hDevInfo = HIDImports.SetupDiGetClassDevs(ref guid, null, IntPtr.Zero, HIDImports.DIGCF_DEVICEINTERFACE);
    
      // create a new interface data struct and initialize its size
      HIDImports.SP_DEVICE_INTERFACE_DATA diData = new HIDImports.SP_DEVICE_INTERFACE_DATA();
      diData.cbSize = Marshal.SizeOf(diData);
    
      // get a device interface to a single device (enumerate all devices)
      while (HIDImports.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref guid, index, ref diData))
      {
        UInt32 size = 0;
    
        // get the buffer size for this device detail instance (returned in the size parameter)
        HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, IntPtr.Zero, 0, out size, IntPtr.Zero);
    
        // create a detail struct and set its size
        HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA diDetail = new HIDImports.SP_DEVICE_INTERFACE_DETAIL_DATA();
    
        //On Win x86, cbSize = 5, On x64, cbSize = 8 i
        diDetail.cbSize = (IntPtr.Size == 8) ? (uint)8 : (uint)5;
    
        // actually get the detail struct
        if (HIDImports.SetupDiGetDeviceInterfaceDetail(hDevInfo, ref diData, ref diDetail, size, out size, IntPtr.Zero))
        {
          // open a read/write handle to our device using the DevicePath returned
          SafeHandle safeHandle = HIDImports.CreateFile(diDetail.DevicePath, FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, HIDImports.EFileAttributes.Overlapped, IntPtr.Zero);
    
          // create an attributes struct and initialize the size
          deviceAttributes = new HIDImports.HIDD_ATTRIBUTES();
          deviceAttributes.Size = Marshal.SizeOf(deviceAttributes);
    
          // get the attributes of the current device
          if (HIDImports.HidD_GetAttributes(safeHandle.DangerousGetHandle(), ref deviceAttributes))
          {
            details.AppendLine("--- HID DEVICE FOUND ---");
            details.AppendLine(String.Format("ProductID: 0x{0}", deviceAttributes.ProductID.ToString("X4")));
            details.AppendLine(String.Format("VendorID: 0x{0}", deviceAttributes.VendorID.ToString("X4")));
            details.AppendLine(String.Format("VersionNumber: 0x{0}", deviceAttributes.VersionNumber.ToString("X4")));
            details.AppendLine(String.Format("Size: 0x{0}", deviceAttributes.Size.ToString("X4")));
            details.AppendLine();
          }
        }
        index++;
      }
    
      return details.ToString();
    }
    

    The method uses HIDImports.cs, whose content is below:

    //////////////////////////////////////////////////////////////////////////////////
    //	HIDImports.cs
    //	For more information: http://wiimotelib.codeplex.com/
    //////////////////////////////////////////////////////////////////////////////////
    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using Microsoft.Win32.SafeHandles;
    
    namespace CreateBinaryFromXml
    {
    	public class HIDImports
    	{
    		// Flags controlling what is included in the device information set built by SetupDiGetClassDevs
    	  internal const int DIGCF_DEFAULT = 0x00000001;       // only valid with DIGCF_DEVICEINTERFACE
        internal const int DIGCF_PRESENT = 0x00000002;
        internal const int DIGCF_ALLCLASSES = 0x00000004;
        internal const int DIGCF_PROFILE = 0x00000008;
        internal const int DIGCF_DEVICEINTERFACE = 0x00000010;
    
    		[Flags]
        internal enum EFileAttributes : uint
    		{
    		  Readonly     = 0x00000001,
    		  Hidden      = 0x00000002,
    		  System      = 0x00000004,
    		  Directory    = 0x00000010,
    		  Archive     = 0x00000020,
    		  Device      = 0x00000040,
    		  Normal      = 0x00000080,
    		  Temporary    = 0x00000100,
    		  SparseFile    = 0x00000200,
    		  ReparsePoint   = 0x00000400,
    		  Compressed    = 0x00000800,
    		  Offline     = 0x00001000,
    		  NotContentIndexed= 0x00002000,
    		  Encrypted    = 0x00004000,
    		  Write_Through  = 0x80000000,
    		  Overlapped    = 0x40000000,
    		  NoBuffering   = 0x20000000,
    		  RandomAccess   = 0x10000000,
    		  SequentialScan  = 0x08000000,
    		  DeleteOnClose  = 0x04000000,
    		  BackupSemantics = 0x02000000,
    		  PosixSemantics  = 0x01000000,
    		  OpenReparsePoint = 0x00200000,
    		  OpenNoRecall   = 0x00100000,
    		  FirstPipeInstance= 0x00080000
    		}
    
    		[StructLayout(LayoutKind.Sequential)]
        internal struct SP_DEVINFO_DATA
    		{
    			public uint cbSize;
    			public Guid ClassGuid;
    			public uint DevInst;
    			public IntPtr Reserved;
    		}
    
    		[StructLayout(LayoutKind.Sequential)]
        internal struct SP_DEVICE_INTERFACE_DATA
    		{
    			public int cbSize;
    			public Guid InterfaceClassGuid;
    			public int Flags;
    			public IntPtr RESERVED;
    		}
    
    		[StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
    		{
    			public UInt32 cbSize;
    			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    			public string DevicePath;
    		}
    
    		[StructLayout(LayoutKind.Sequential)]
    		public struct HIDD_ATTRIBUTES
    		{
    			public int Size;
    			public short VendorID;
    			public short ProductID;
    			public short VersionNumber;
    		}
    
    		[DllImport(@"hid.dll", CharSet=CharSet.Auto, SetLastError = true)]
        internal static extern void HidD_GetHidGuid(out Guid gHid);
    
    		[DllImport("hid.dll")]
        internal static extern Boolean HidD_GetAttributes(IntPtr HidDeviceObject, ref HIDD_ATTRIBUTES Attributes);
    
    		[DllImport("hid.dll")]
        internal extern static bool HidD_SetOutputReport(
    			IntPtr HidDeviceObject,
    			byte[] lpReportBuffer,
    			uint ReportBufferLength);
    
    		[DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern IntPtr SetupDiGetClassDevs(
    			ref Guid ClassGuid,
    			[MarshalAs(UnmanagedType.LPTStr)] string Enumerator,
    			IntPtr hwndParent,
    			UInt32 Flags
    			);
    
    		[DllImport(@"setupapi.dll", CharSet=CharSet.Auto, SetLastError = true)]
        internal static extern Boolean SetupDiEnumDeviceInterfaces(
    			IntPtr hDevInfo,
    			IntPtr devInvo,
    			ref Guid interfaceClassGuid,
    			UInt32 memberIndex,
    			ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData
    		);
    
    		[DllImport(@"setupapi.dll", SetLastError = true)]
        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(
    			IntPtr hDevInfo,
    			ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
    			IntPtr deviceInterfaceDetailData,
    			UInt32 deviceInterfaceDetailDataSize,
    			out UInt32 requiredSize,
    			IntPtr deviceInfoData
    		);
    
    		[DllImport(@"setupapi.dll", SetLastError = true)]
        internal static extern Boolean SetupDiGetDeviceInterfaceDetail(
    			IntPtr hDevInfo,
    			ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
    			ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
    			UInt32 deviceInterfaceDetailDataSize,
    			out UInt32 requiredSize,
    			IntPtr deviceInfoData
    		);
    
    		[DllImport(@"setupapi.dll", CharSet=CharSet.Auto, SetLastError = true)]
        internal static extern UInt16 SetupDiDestroyDeviceInfoList(IntPtr hDevInfo);
    
    		[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        internal static extern SafeFileHandle CreateFile(
    			string fileName,
    			[MarshalAs(UnmanagedType.U4)] FileAccess fileAccess,
    			[MarshalAs(UnmanagedType.U4)] FileShare fileShare,
    			IntPtr securityAttributes,
    			[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
    			[MarshalAs(UnmanagedType.U4)] EFileAttributes flags,
    			IntPtr template);
    
    			[DllImport("kernel32.dll", SetLastError=true)]
    			[return: MarshalAs(UnmanagedType.Bool)]
    			public static extern bool CloseHandle(IntPtr hObject);
    	}
    }
    
    

     

    • Marked as answer by BBauer42 Wednesday, March 16, 2011 12:19 PM
    Wednesday, March 16, 2011 12:18 PM