THX
You might find the following code helpful. You need a Form, inside a GoupBox, 2 Labels and a TextBox.
(Keep in mind, it's not production code.)
if You insert/remove an USB-"Drive"-Device, the list of removable devices will be updated.
if You insert/remove the Yubico, this keyboards-Device' ID will be shown in the Textbox "txtDevices".
The main procedure is 'OnDeviceChange', there you look for NewID OldID which you may ask with .Contains(...
Have fun.
Richard
MS Visual Studio 2010, C#, .NET Framework 4 Client Profile
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Management;
using System.Runtime.InteropServices;
namespace ShowDrives
{
public partial class Form1 : Form
{
public struct _myDriveInfo
{
public string _driveletter;
public string _drivelabel;
public string _drivetype;
}
List<_myDriveInfo> _drives = new List<_myDriveInfo>();
List<string> _keyboards = new List<string>();
List<string> _oldKeyboards = new List<string>();
public Form1()
{
InitializeComponent();
RegisterHidNotification();
CheckKeyboardDevice();
}
public void FindDrives()
{
_drives.Clear();
var drives = DriveInfo.GetDrives();
foreach (var drive in drives)
{
if ((drive.IsReady) & (drive.DriveType == DriveType.Removable))
{
_myDriveInfo MyDriveInfo = new _myDriveInfo();
MyDriveInfo._driveletter = drive.Name;
MyDriveInfo._drivelabel = drive.VolumeLabel;
MyDriveInfo._drivetype = drive.DriveType.ToString();
_drives.Add(MyDriveInfo);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
FindDrives();
Int32 TopLoc;
for (int i = 0; i < _drives.Count(); i++)
{
RadioButton rdo = new RadioButton();
rdo.Name = "rdb " + i.ToString();
rdo.AutoSize = true;
rdo.Text = _drives[i]._driveletter + " Label: '" + _drives[i]._drivelabel + "', Type: " + _drives[i]._drivetype;
TopLoc = 20 + 30 * i;
rdo.Location = new Point(15, TopLoc);
groupBox1.Height = TopLoc + rdo.Height + 6;
groupBox1.Controls.Add(rdo);
}
lblMessage.Text = "Please select USB-Drive";
lblMessage.Location = new Point(groupBox1.Left, groupBox1.Top + groupBox1.Height + 15);
}
private void UpdateDriveList()
{
for (int i = 0; i < groupBox1.Controls.Count; i++)
{
RadioButton rdo = (RadioButton)groupBox1.Controls[i];
rdo.Dispose();
}
groupBox1.Controls.Clear();
FindDrives();
Int32 TopLoc;
for (int i = 0; i < _drives.Count(); i++)
{
RadioButton rdo = new RadioButton();
rdo.Name = "rdb " + i.ToString();
rdo.AutoSize = true;
rdo.Text = _drives[i]._driveletter + " Label: '" + _drives[i]._drivelabel + "', Type: " + _drives[i]._drivetype;
TopLoc = 20 + 30 * i;
rdo.Location = new Point(15, TopLoc);
groupBox1.Height = TopLoc + rdo.Height + 6;
groupBox1.Controls.Add(rdo);
}
lblMessage.Location = new Point(groupBox1.Left, groupBox1.Top + groupBox1.Height + 15);
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WinAPI.WM_DEVICECHANGE: OnDeviceChange(ref m); break;
}
base.WndProc(ref m);
}
void OnDeviceChange(ref Message msg)
{
int wParam = (int)msg.WParam;
if (wParam == WinAPI.DBT_DEVICEARRIVAL)
{
label1.Text = "USB-Device plugged in";
//CheckDevice();
CreateOldKeyboardList();
CheckKeyboardDevice();
string NewID = FindMissingElement(_oldKeyboards, _keyboards);
txtDevices.AppendText(NewID + Environment.NewLine);
}
else if (wParam == WinAPI.DBT_DEVICEREMOVECOMPLETE)
{
label1.Text = "USB-Device removed";
CreateOldKeyboardList();
CheckKeyboardDevice();
string OldID = FindMissingElement(_keyboards, _oldKeyboards);
txtDevices.AppendText(OldID + Environment.NewLine);
}
UpdateDriveList();
}
void RegisterHidNotification()
{
string e = "";
WinAPI.DEV_BROADCAST_DEVICEINTERFACE dbi = new WinAPI.DEV_BROADCAST_DEVICEINTERFACE();
int size = Marshal.SizeOf(dbi);
dbi.dbcc_size = size;
dbi.dbcc_devicetype = WinAPI.DBT_DEVTYP_DEVICEINTERFACE;
dbi.dbcc_reserved = 0;
dbi.dbcc_classguid = WinAPI.GUID_DEVINTERFACE_HID;
dbi.dbcc_name = 0;
IntPtr buffer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(dbi, buffer, true);
IntPtr r = WinAPI.RegisterDeviceNotification(Handle, buffer, WinAPI.DEVICE_NOTIFY_WINDOW_HANDLE);
if (r == IntPtr.Zero)
{
e = WinAPI.GetLastError().ToString();
MessageBox.Show(e);
}
}
void CheckDevice()
{
IntPtr devinfo = WinAPI.SetupDiGetClassDevs(ref WinAPI.GUID_DEVCLASS_KEYBOARD, IntPtr.Zero, IntPtr.Zero, WinAPI.DIGCF_PRESENT);
WinAPI.SP_DEVINFO_DATA devInfoSet = new WinAPI.SP_DEVINFO_DATA();
devInfoSet.cbSize = Marshal.SizeOf(typeof(WinAPI.SP_DEVINFO_DATA));
/*
if (Win32.SetupDiEnumDeviceInfo(devinfo, 0, ref devInfoSet))
{
label1.Text = "keyboard";
}
*/
}
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 = WinAPI.SetupDiGetClassDevs(
ref WinAPI.GUID_DEVCLASS_KEYBOARD,
IntPtr.Zero,
IntPtr.Zero,
WinAPI.DIGCF_PRESENT);
WinAPI.SP_DEVINFO_DATA devInfoSet =
new WinAPI.SP_DEVINFO_DATA();
devInfoSet.cbSize =
Marshal.SizeOf(typeof(WinAPI.SP_DEVINFO_DATA));
_keyboards.Clear();
while (WinAPI.SetupDiEnumDeviceInfo(devinfo, count, ref devInfoSet))
{
count++;
_keyboards.Add(CM_Get_Device_ID(devInfoSet.DevInst));
}
WinAPI.SetupDiDestroyDeviceInfoList(devinfo);
}
private string FindMissingElement(List<string> Stock, List<string> Elements)
{
string result = "";
foreach (string Element in Elements)
{
if(!(Stock.Contains(Element)))
{
result = Element;
break;
}
}
return result;
}
private void CreateOldKeyboardList()
{
_oldKeyboards.Clear();
foreach (string keyboard in _keyboards)
{
_oldKeyboards.Add(keyboard);
}
}
}
class WinAPI
{
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();
public const int DIGCF_PRESENT = 2;
public static Guid GUID_DEVCLASS_KEYBOARD = new Guid("4D36E96B-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;
}
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiDestroyDeviceInfoList
(
IntPtr DeviceInfoSet
);
}
}