Last time I wanted to perform detection of a USB device with .NET I overrode the WndProc method in the main form of the application to capture and route the windows messages through to the library.
WPF does not natively have the WndProc as it uses a different messaging architecture, however an interop has been provided details of which can be found in amongst "WPF and Win32 Interoperation Overview"
Just want example code?
Here is some example code to get you started. It detects the USB insertion and removal for a U.B. Funkey Game unit – it was what was on my desk when I needed something to test with… U.B. Funkeys Official Site
Find the device class ID from your device manger page for the device you want to use. In device manager, expand the node for the USB device in question and look for a GUID that is found under the properties, then details tab. The GUID uniquely identifies the USB device.
Get the message
We ultimately want to get the WM_DEVICECHANGE message from windows and register the device we are looking for so that we also get passed the WParam information about which device has changed and raise events as required. If you don’t register an interest in the specific device you merely get a DBT_DEVNODES_CHANGED = &H7 returned that is not really too helpful.
Public Sub ProcessWinMessage(ByVal msg As Integer, ByVal wParam As IntPtr, _
ByVal IParam As IntPtr)
If msg = WM_DEVICECHANGE Then
Select Case wParam
RaiseEvent AfterUSBInserted(Me, New EventArgs)
RaiseEvent AfterUSBRemoved(Me, New EventArgs)
There is plenty on code project website about these messages and how to use them in traditional windows with .NET. However we want to use WPF as an application type so lets move on…
To get around the fact that WPF has no WndProc to override we have to use another technique. Override the OnSourceInitalized and get an instance of the Interop.WindowInteropHelper class initialised with the WPF form we are using. Using this interop object we can access a windows handle and can create a hook with AddHook to get hold of the windows events. This hook simply calls a delegate method for processing those messages, in this example oUsbFunkey.HwndHandler.
Protected Overrides Sub OnSourceInitialized(ByVal e As System.EventArgs)
Dim MainFormWinInteropHelper As New Interop.WindowInteropHelper(Me)
HwndHandler function gets the messages from the message hooking above
Public Function HwndHandler(ByVal hwnd As IntPtr, ByVal msg As Integer, _
ByVal wParam As IntPtr, ByVal IParam As IntPtr, _
ByRef handled As Boolean) As IntPtr
ProcessWinMessage(msg, wParam, IParam)
handled = False
Register interest in the USB device
The code next registers the device we are interested in, namely the Funkey and its class id of "c671678c-82c1-43f3-d700-0049433e9a4b".
Private Const USBClassID As String = _
Public Sub RegisterDeviceNotification(ByVal hwnd As IntPtr)
Dim deviceInterface As New Win32.DEV_BROADCAST_DEVICEINTERFACE()
Dim size As Integer = Marshal.SizeOf(deviceInterface)
deviceInterface.dbcc_size = size
deviceInterface.dbcc_devicetype = Win32.DBT_DEVTYP_DEVICEINTERFACE
deviceInterface.dbcc_reserved = 0
deviceInterface.dbcc_classguid = New Guid(USBClassID).ToByteArray
Dim buffer As IntPtr = Nothing
buffer = Marshal.AllocHGlobal(size)
Marshal.StructureToPtr(deviceInterface, buffer, True)
Dim r As IntPtr = Nothing
r = Win32.RegisterDeviceNotification(hwnd, buffer, _
Win32.DEVICE_NOTIFY_WINDOW_HANDLE Or _
This registration ensures we get details about when this device is inserted or removed through the previously set up message hook. The registration calls through to the registerdevicenotification function in user32.dll. When you have finished listening you should also call the UnregisterDeviceNotification function, something I’ve not done for this example.
<DllImport("user32.dll", SetLastError:=True)> _
Public Shared Function RegisterDeviceNotification( _
ByVal IntPtr As IntPtr, ByVal NotificationFilter As IntPtr, _
ByVal Flags As Int32) As IntPtr
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Public Shared Function UnregisterDeviceNotification( _
ByVal hHandle As IntPtr) As UInteger
When the message is received I choose to raise an event back to the WPF form that in turn shows or hides a photo of my Funkey.
This is a get you started guide. Check out the various elements of this solution so you understand how each part works, and thus add appropriate robustness to it for your application of the code.
Download the Example Code
WpfFunkeyApplication.zip (235.51 kb)