Skip to content

Instantly share code, notes, and snippets.

@emoacht
Last active May 3, 2021 05:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emoacht/cc2f336acc388d8921079d53a8f4e96b to your computer and use it in GitHub Desktop.
Save emoacht/cc2f336acc388d8921079d53a8f4e96b to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.ServiceProcess;
public partial class DeviceDetectService : ServiceBase
{
public DeviceDetectService()
{
InitializeComponent();
}
private static readonly Guid GUID_DEVINTERFACE_USB_DEVICE = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED");
private IntPtr _notificationHandle;
protected override void OnStart(string[] args)
{
DeviceNotification.Unregister(_notificationHandle);
_notificationHandle = DeviceNotification.Register(this.ServiceHandle, GUID_DEVINTERFACE_USB_DEVICE);
}
protected override void OnStop()
{
DeviceNotification.Unregister(_notificationHandle);
_notificationHandle = IntPtr.Zero;
}
protected override void OnCustomCommand(int command)
{
switch (command)
{
case DeviceNotification.SERVICE_CONTROL_DEVICEEVENT:
Debug.WriteLine("USB device event received!");
this.EventLog.WriteEntry("USB device event received!");
break;
}
}
}
public static class DeviceNotification
{
[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr RegisterDeviceNotification(
IntPtr hRecipient,
IntPtr NotificationFilter,
uint Flags);
[DllImport("User32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnregisterDeviceNotification(IntPtr Handle);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct DEV_BROADCAST_DEVICEINTERFACE
{
public uint dbcc_size;
public uint dbcc_devicetype;
public uint dbcc_reserved;
public Guid dbcc_classguid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string dbcc_name;
}
private const int DEVICE_NOTIFY_SERVICE_HANDLE = 0x00000001;
private const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005;
public const int SERVICE_CONTROL_DEVICEEVENT = 0x0000000B;
/// <summary>
/// Registers to device events.
/// </summary>
/// <param name="serviceHandle">Service status handle</param>
/// <param name="classGuid">Device interface class Guid</param>
/// <returns>Device notification handle</returns>
public static IntPtr Register(IntPtr serviceHandle, Guid classGuid)
{
var dbcc = new DEV_BROADCAST_DEVICEINTERFACE
{
dbcc_size = (uint)Marshal.SizeOf<DEV_BROADCAST_DEVICEINTERFACE>(),
dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE,
dbcc_classguid = classGuid
};
var buffer = IntPtr.Zero;
try
{
buffer = Marshal.AllocHGlobal((int)dbcc.dbcc_size);
Marshal.StructureToPtr(dbcc, buffer, true);
return RegisterDeviceNotification(
serviceHandle,
buffer,
DEVICE_NOTIFY_SERVICE_HANDLE);
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to register.\r\n{ex}");
return IntPtr.Zero;
}
finally
{
if (buffer != IntPtr.Zero)
Marshal.FreeHGlobal(buffer);
}
}
/// <summary>
/// Unregisters from device events.
/// </summary>
/// <param name="notificationHandle">Device notification handle</param>
public static void Unregister(IntPtr notificationHandle)
{
if (notificationHandle != IntPtr.Zero)
UnregisterDeviceNotification(notificationHandle);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment