Page 1 of 1

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

Posted: Sat Mar 13, 2010 2:46 am
by Neo
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 3535 times