How to detect USB devices, mouse, keyboard (HID) using C#

.NET programming topics
Post Reply
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

How to detect USB devices, mouse, keyboard (HID) using C#

Post by Neo » Sat Mar 13, 2010 2:46 am

Thi code will show you how to detect Human Input Devices (HID) like USB devices, mouse, keyboard, keypad, joystick, etc... If you want to detect all USB devices, uses GUID_DEVINTERFACE_USB_DEVICE = "A5DCBF10-6530-11D2-901F-00C04FB951ED" instead.

Code: Select all

using System.Runtime.InteropServices;

namespace WindowsApplication1
{
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Label label1;

        public Form1()
        {
            InitializeComponent();
            RegisterHidNotification();
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case Win32.WM_DEVICECHANGE: OnDeviceChange(ref m); break;
            }
            base.WndProc(ref m);
        }

        void OnDeviceChange(ref Message msg)
        {
            int wParam = (int)msg.WParam;
            if (wParam == Win32.DBT_DEVICEARRIVAL) label1.Text = "Arrival";
            else if (wParam == Win32.DBT_DEVICEREMOVECOMPLETE) label1.Text =
             "Remove";
        }

        void RegisterHidNotification()
        {
            Win32.DEV_BROADCAST_DEVICEINTERFACE dbi = new
            Win32.DEV_BROADCAST_DEVICEINTERFACE();
            int size = Marshal.SizeOf(dbi);
            dbi.dbcc_size = size;
            dbi.dbcc_devicetype = Win32.DBT_DEVTYP_DEVICEINTERFACE;
            dbi.dbcc_reserved = 0;
            dbi.dbcc_classguid = Win32.GUID_DEVINTERFACE_HID;
            dbi.dbcc_name = 0;
            IntPtr buffer = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(dbi, buffer, true);
            IntPtr r = Win32.RegisterDeviceNotification(Handle, buffer,
            Win32.DEVICE_NOTIFY_WINDOW_HANDLE);
            if (r == IntPtr.Zero)
                label1.Text = Win32.GetLastError().ToString();
        }
    }

    class Win32
    {
        public const int
        WM_DEVICECHANGE = 0x0219;
        public const int
        DBT_DEVICEARRIVAL = 0x8000,
        DBT_DEVICEREMOVECOMPLETE = 0x8004;
        public const int
        DEVICE_NOTIFY_WINDOW_HANDLE = 0,
        DEVICE_NOTIFY_SERVICE_HANDLE = 1;
        public const int
        DBT_DEVTYP_DEVICEINTERFACE = 5;
        public static Guid
        GUID_DEVINTERFACE_HID = new
        Guid("4D1E55B2-F16F-11CF-88CB-001111000030");

        [StructLayout(LayoutKind.Sequential)]
        public class DEV_BROADCAST_DEVICEINTERFACE
        {
            public int dbcc_size;
            public int dbcc_devicetype;
            public int dbcc_reserved;
            public Guid dbcc_classguid;
            public short dbcc_name;
        }

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr RegisterDeviceNotification(
        IntPtr hRecipient,
        IntPtr NotificationFilter,
        Int32 Flags);

        [DllImport("kernel32.dll")]
        public static extern int GetLastError();
    }
}
Here is code for mouse detection. For keyboard, use GUID_DEVCLASS_KEYBOARD = {4D36E96B-E325-11CE-BFC1-08002BE10318} instead.

Code: Select all

public class Form1 : System.Windows.Forms.Form
{
    void CheckDevice()
    {
        IntPtr devinfo = Win32.SetupDiGetClassDevs(ref
Win32.GUID_DEVCLASS_MOUSE, IntPtr.Zero, IntPtr.Zero, Win32.DIGCF_PRESENT);
        Win32.SP_DEVINFO_DATA devInfoSet = new Win32.SP_DEVINFO_DATA();
        devInfoSet.cbSize = Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));
        if (Win32.SetupDiEnumDeviceInfo(devinfo, 0, ref devInfoSet))
            label1.Text = "mouse";
    }
}

class Win32
{
    public const int DIGCF_PRESENT = 2;

    public static Guid GUID_DEVCLASS_MOUSE = new
    Guid("4D36E96F-E325-11CE-BFC1-08002BE10318");

    [DllImport("setupapi.dll")]
    public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid,
    IntPtr Enumerator, IntPtr hWndParent, int Flags);

    [DllImport("setupapi.dll")]
    public static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet,
    int Supplies, ref SP_DEVINFO_DATA DeviceInfoData);

    [StructLayout(LayoutKind.Sequential)]
    public struct SP_DEVINFO_DATA
    {
        public int cbSize;
        public Guid ClassGuid;
        public int DevInst;
        public int Reserved;
    }
}
If you want to list down mouse or keyboard at the time of detection on a list box use following code.

Code: Select all

    private void CheckMouseDevice()
    {
        int count = 0;
        IntPtr devinfo = Win32.SetupDiGetClassDevs(
        ref Win32.GUID_DEVCLASS_MOUSE,
        IntPtr.Zero,
        IntPtr.Zero,
        Win32.DIGCF_PRESENT);
        Win32.SP_DEVINFO_DATA devInfoSet =
        new Win32.SP_DEVINFO_DATA();
        devInfoSet.cbSize =
        Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));

        this.lbMouseList.Items.Clear();
        while (Win32.SetupDiEnumDeviceInfo(devinfo, count,
        ref devInfoSet))
        {
            count++;
            this.lbMouseList.Items.Add(
            devInfoSet.DevInst.ToString());
        }
        this.lblMouseCount.Text = count.ToString();
        Win32.SetupDiDestroyDeviceInfoList(devinfo);

        labelKeyboard.Text = "keyboard\n" + Win32.CM_Get_Device_ID(devInfoSet.DevInst);
    }


    public const int CR_SUCCESS = 0;
    [DllImport("cfgmgr32.dll")]
    public static extern int CM_Get_Device_ID(int DevInst, IntPtr Buffer, int BufferLen, int Flags);

    public static string CM_Get_Device_ID(int DevInst)
    {
        string s = null;
        int len = 300;
        IntPtr buffer = Marshal.AllocHGlobal(len);
        int r = CM_Get_Device_ID(DevInst, buffer, len, 0);
        if (r == CR_SUCCESS) s = Marshal.PtrToStringAnsi(buffer);
        return s;
    }

    private void CheckKeyboardDevice()
    {
        int count = 0;
        IntPtr devinfo = Win32.SetupDiGetClassDevs(
        ref Win32.GUID_DEVCLASS_KEYBOARD,
        IntPtr.Zero,
        IntPtr.Zero,
        Win32.DIGCF_PRESENT);

        Win32.SP_DEVINFO_DATA devInfoSet =
        new Win32.SP_DEVINFO_DATA();
        devInfoSet.cbSize =
        Marshal.SizeOf(typeof(Win32.SP_DEVINFO_DATA));

        this.lbKeyboardList.Items.Clear();
        while (Win32.SetupDiEnumDeviceInfo(devinfo, count,
        ref devInfoSet))
        {
            count++;
            this.lbKeyboardList.Items.Add(
            devInfoSet.DevInst.ToString());
        }
        this.lblKeyboardCount.Text = count.ToString();
        Win32.SetupDiDestroyDeviceInfoList(devinfo);
    }
The resulting device id is something like "ACPI\PNP0F13\4&33A96545&0". It points to registry branch under [hkey_local_machine\system\currentcontrolset\enum]. Check whether it is an expected device.

See this nicely working USB drive detection C# project as well.
SimpleDetector.zip
(56.67 KiB) Downloaded 3419 times
Post Reply

Return to “.NET Programming”