RegisterDeviceNotification in WPF
-
Saturday, April 21, 2007 11:41 AM
Hi all,
I am writing a C# class library for a WPF application. The class library should raise an event whenever some USB device is plugged in/plugged out.
I am registering the USB devices, using RegisterRawInputDevices API and I am able to process WM_Input messages in the library.
I am also able to get WM_DEVICECHANGE messages. But the values of WParam is always 7 whereas I am hoping to get
DBT_DEVICEARRIVAL = 0x8000 or DBT_DEVICEREMOVECOMPLETE = 0x8004
I referred to an example from http://www.dotnet247.com/247reference/msgs/32/164968.aspx(window application example).
It talks about using RegisterDeviceNotification() method. This method needs a handle.
I am passing the current window handle of the WPF application using
System.Windows.Interop.WindowInteropHelper temp = new WindowInteropHelper(this.currentWindow);
windowHandle = temp.Handle;
RegisterDeviceNotification(windowHandle, Buffer, DEVICE_NOTIFY_WINDOW_HANDLE);
However, I am still not able to get DBT_DEVICEARRIVAL/ DBT_DEVICEREMOVECOMPLETE values in WParam in the WM_DEVICECHANGE message?
Any help would be greatly appreciated.
Regards
Pankaj
All Replies
-
Sunday, April 22, 2007 2:44 PM
This code will help you
Code SnippetWqlEventQuery
_q = new WqlEventQuery("__InstanceOperationEvent", "TargetInstance ISA 'Win32_USBControllerDevice' ");_q.WithinInterval = TimeSpan.FromSeconds(1);
ManagementEventWatcher _w = new ManagementEventWatcher(_q);
_w.EventArrived += new EventArrivedEventHandler(onEventArrived);
_w.Start();
void onEventArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject _o = e.NewEvent["TargetInstance"] as ManagementBaseObject;
if (_o != null)
{
using (ManagementObject mo = new ManagementObject(_o["Dependent"].ToString()))
{
if (mo != null)
{
try
{
if(mo.GetPropertyValue("DeviceID").ToString() != string.Empty)
{
//connected
}
}
catch (ManagementException ex)
{
//disconnected
}
}
}
}
}
- Proposed As Answer by Omar Elsherif Monday, July 23, 2012 11:36 PM
-
Sunday, April 22, 2007 3:03 PM
Hi Tamir,
Thanks for your reply !
The approach you suggested uses ManagementEventWatcher.
Is there any way by which I can RegisterDeviceNotification () API and process DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE in WPF?
This is working fine in Windows application (http://www.dotnet247.com/247reference/msgs/32/164968.aspx)
What is it, that needs to be done to get this working in C# class library, in addition what I have done in post 1 ?
Regards
Pankaj
-
Monday, April 23, 2007 8:36 AM
In order to get current window handle use following (Win32 class is the same as in the sample within your link)
Code Snippetprotected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
if (hwndSource != null)
{
hwndSource.AddHook(new HwndSourceHook(this.hwndSourceHook));
}
}
IntPtr hwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == Win32.WM_DEVICECHANGE)
{
if ((int)wParam == Win32.DBT_DEVICEARRIVAL)
{
RaiseDeviceArrived();
}
else if ((int)wParam == Win32.DBT_DEVICEREMOVECOMPLETE)
{
RaiseDeviceRemoved();
}
}
return IntPtr.Zero;
}
-
Wednesday, January 09, 2008 3:24 AM
I tried this WPF code, but wParam is 7 whether the device is added or removed...any ideas on why that is?
Here's a bit more info as to what's going on: the 7 is DBT_DEVNODES_CHANGED. This is supposed to be the parameter that is sent when the window has not called RegisterDeviceNotification (calling RDN is supposed to result in the more specific messages coming in). However, even using the original WinForm code (as a WinForm app), I still get DBT_DEVNODES_CHANGED. In fact, every sample for listening for device add/remove returns 7 on my machine. If I were to take a guess as to the issue, I'd say it has something to do with me running Vista (maybe as part of its heightened security, there's more hoops to jump through to RegisterDeviceNotification); I'll try my test app tomorrow on an XP machine to see if the value is different for that one. In the meantime, I'll see if I can find some kind of release note for Vista related to that API
-
Thursday, January 10, 2008 7:31 AMTook a little playing around, but basically, if you call RegisterDeviceNotification with
Win32
.DEVICE_NOTIFY_WINDOW_HANDLE | Win32.DEVICE_NOTIFY_ALL_INTERFACE_CLASSES instead of justWin32
.DEVICE_NOTIFY_WINDOW_HANDLE, you should be able to start getting the Added/Removed messages in addition to the NodesChanged message. -
Thursday, June 19, 2008 11:37 PMUsing both DEVICE_NOTIFY_ALL_INTERFACE_CLASSES and DEVICE_NOTIFY_WINDOW_HANDLE worked the first time I ran it and then it was back to 7 again. Do I ahve to restart my computer? ;)
-
Monday, July 07, 2008 9:51 PMKeith,
Can you post the code sample where you called RegisterDeviceNotification?
-
Wednesday, April 29, 2009 3:04 PM
im doing the same thing but i can find a way to detect a removed device the code i used for deteting a new devies is ...
(btw this ant my code i got it off anouther page)
private const int WM_DEVICECHANGE = 0x0219;
private const int LOGICAL_VOLUME = 2;
private readonly IntPtr DBT_DEVICEARRIVAL = new IntPtr(0x8000);protected override void WndProc(ref Message m)
{
if ((m.Msg == WM_DEVICECHANGE) && (m.WParam == DBT_DEVICEARRIVAL))
{
int deviceType = Marshal.ReadInt32(m.LParam, sizeof(int));if (deviceType == LOGICAL_VOLUME)
{
uint unitMask = (uint)Marshal.ReadInt32(m.LParam, sizeof(int) * 3);if (unitMask != 0)
{
char driveLetter = DriveLetterFromUnitMask(unitMask);
Debug.WriteLine("Drive was inserted: " + driveLetter);// Now copy your file to the drive specified by 'driveLetter'.
}
}
}base.WndProc(ref m);
}private char DriveLetterFromUnitMask(uint unitMask)
{
for (int bitIndex = 0, bit = 1; bitIndex < 32; ++bitIndex, bit <<= 1)
{
if ((unitMask & bit) != 0)
{
return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[bitIndex];
}
}return '?';
}
sam eden
porgramer that will program all day lol sites.google.com/site/sameden2 -
Friday, July 17, 2009 10:44 AM
I realize this post is pretty old but I'll state the answer here as I could not find an answer anywhere online. It took me all night to figure this out. In the WndProc handler, t he WParam is always 7and IParam is always 0 on attach/detach as long as CreateFile(...) has not yet been called to create the file handle for your device.
By the way, I did it using the RegisterDeviceNotification() API.
Anderson John
-
Wednesday, April 04, 2012 1:53 PM
As andyfoxx said: This post is old, but I did not find any solution to the same kind of problem in the web. So I solved it by myself.
Thing is that if you want to get more information from a USB device than just wParam = 7 you need to RegisterDeviceNotification for your device(s) before you wait for the WndProc Message.
I did that by using the user32.dll in C#
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] internal static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags);This is the function I need. I use it like:
deviceNotificationHandle = RegisterDeviceNotification(formHandle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE);
formHandle is as the name says the Handle of the control.
DEVICE_NOTIFY_WINDOW_HANDLE is a int32 constant which equals 0.
devBroadcastDeviceInterfaceBuffer is a little complicated. The source is a open source snippet. Here you are:DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE(); IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero; Int32 size = 0; try { // Set the parameters in the DEV_BROADCAST_DEVICEINTERFACE structure. // Set the size. size = Marshal.SizeOf(devBroadcastDeviceInterface); devBroadcastDeviceInterface.dbcc_size = size; // Request to receive notifications about a class of devices. devBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; devBroadcastDeviceInterface.dbcc_reserved = 0; // Specify the interface class to receive notifications about. devBroadcastDeviceInterface.dbcc_classguid = classGuid; // Allocate memory for the buffer that holds the DEV_BROADCAST_DEVICEINTERFACE structure. devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size); // Copy the DEV_BROADCAST_DEVICEINTERFACE structure to the buffer. // Set fDeleteOld True to prevent memory leaks. Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);This did it for me. I hope I could help you. (I know this is almost the same andyfoxx posted. Just a bit of code for you ^^)
Yours
fieldtracker

