I am trying to implement this solution by Hans Passant here for HID plug and play scanner: How to receive Plug & Play device notifications without a windows form
It works great and gives me top level win messages for DBT_DEVNODES_CHANGED 0x0007 "A device has been added to or removed from the system." However I need to register for notifications to get DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE messages. So I added a method for it but I am getting an error during call to NativeMethods.RegisterDeviceNotification "MInstance.Handle threw System.InvalidOperationException" Here is my code, includes my RegisterNotifications() method and slightly modded original code from above URL.
public static DeviceNotificationControl MInstance { get; private set; }
public static void Start(string devicePathName)
{
Thread t = new Thread(() => runForm(devicePathName));
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
}
public static void Stop()
{
if (MInstance == null) throw new InvalidOperationException("Notifier not started");
DeviceNotify = null;
MInstance.Invoke(new MethodInvoker(MInstance.endForm));
}
public static DeviceNotificationControl GetInstance()
{
if (MInstance != null)
return MInstance;
return null;
}
[STAThread]
private static void runForm(string devicePathName)
{
Application.Run(new DeviceNotificationControl(devicePathName));
}
protected override void SetVisibleCore(bool value)
{
// Prevent window visibility
if (MInstance == null)
{
CreateHandle();
if (this.IsHandleCreated)
MInstance = this;
}
value = false;
base.SetVisibleCore(value);
}
private void endForm()
{
this.Close();
}
public static bool RegisterNotifications()
{
if (_notificationHandle != IntPtr.Zero)
throw new InvalidOperationException("Already registered for notifications.");
if (MInstance == null)
throw new InvalidOperationException("The notification control has not been created.");
var hidGuid = new Guid("4d1e55b2-f16f-11cf-88cb-001111000030");
NativeMethods.DEV_BROADCAST_DEVICEINTERFACE devBroadcast = new NativeMethods.DEV_BROADCAST_DEVICEINTERFACE();
IntPtr devBroadcastBuffer = IntPtr.Zero;
int size = Marshal.SizeOf(devBroadcast);
devBroadcast.dbcc_reserved = 0;
devBroadcast.dbcc_size = size;
devBroadcast.dbcc_devicetype = NativeMethods.DBT_DEVTYP_DEVICEINTERFACE;
devBroadcast.dbcc_classguid = hidGuid;
try
{
devBroadcastBuffer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(devBroadcast, devBroadcastBuffer, true);
_notificationHandle = NativeMethods.RegisterDeviceNotification(MInstance.Handle, devBroadcastBuffer, NativeMethods.DEVICE_NOTIFY_WINDOW_HANDLE);
Marshal.PtrToStructure(devBroadcastBuffer, devBroadcast);
if (_notificationHandle == IntPtr.Zero)
return false;
return true;
}
finally
{
if (devBroadcastBuffer != IntPtr.Zero)
Marshal.FreeHGlobal(devBroadcastBuffer);
}
}
Any suggestions/ideas are greatly appreciated!