Imports System.Runtime.InteropServices
Imports Microsoft.Win32.SafeHandles
'egl1044
Public Class Form1
''' <summary>
''' Detect USB notifications.
''' </summary>
''' <param name="m"></param>
''' <remarks></remarks>
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Dim lpdb As UsbNotification.DevBroadcastHdr
Dim lpdbv As UsbNotification.DevBroadcastVolume
Dim lpdbdi As UsbNotification.DevBroadcastDeviceInterface
Static fUsb As Boolean
If m.Msg = UsbNotification.WM_DEVICECHANGE Then
Select Case m.WParam.ToInt32
Case UsbNotification.DBT_DEVICEARRIVAL
lpdb = CType(m.GetLParam(lpdb.GetType), UsbNotification.DevBroadcastHdr)
If lpdb.dbch_devicetype = UsbNotification.DBT_DEVTYP_DEVICEINTERFACE Then
lpdbdi = CType(m.GetLParam(lpdbdi.GetType), UsbNotification.DevBroadcastDeviceInterface)
fUsb = True
End If
If lpdb.dbch_devicetype = UsbNotification.DBT_DEVTYP_VOLUME AndAlso fUsb Then
lpdbv = CType(m.GetLParam(lpdbv.GetType), UsbNotification.DevBroadcastVolume)
fUsb = False
' Inserted
Debug.Print("Inserted @ drive= {0}", UsbNotification.GetDrive(lpdbv.DBCV_UnitMask))
End If
Case UsbNotification.DBT_DEVICEREMOVECOMPLETE
lpdb = CType(m.GetLParam(lpdb.GetType), UsbNotification.DevBroadcastHdr)
If lpdb.dbch_devicetype = UsbNotification.DBT_DEVTYP_DEVICEINTERFACE AndAlso fUsb Then
lpdbdi = CType(m.GetLParam(lpdbdi.GetType), UsbNotification.DevBroadcastDeviceInterface)
fUsb = True
End If
If lpdb.dbch_devicetype = UsbNotification.DBT_DEVTYP_VOLUME Then
lpdbv = CType(m.GetLParam(lpdbv.GetType), UsbNotification.DevBroadcastVolume)
fUsb = False
' Removed
Debug.Print("Removed @ drive= {0}", UsbNotification.GetDrive(lpdbv.DBCV_UnitMask))
End If
End Select
End If
MyBase.WndProc(m)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
UsbNotification.Start(Me.Handle)
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
UsbNotification.Cancel()
End Sub
End Class
''' <summary>
''' Registers for USB notifications.
''' </summary>
''' <remarks></remarks>
Public Class UsbNotification
Public Const WM_DEVICECHANGE As Integer = &H219
Public Const DBT_DEVICEARRIVAL As Integer = 32768
Public Const DBT_DEVICEREMOVECOMPLETE As Integer = 32772
Public Const DBT_DEVTYP_DEVICEINTERFACE As Integer = 5
Public Const DBT_DEVTYP_VOLUME As Integer = &H2
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure DevBroadcastHdr
Dim dbch_size As UInt32
Dim dbch_devicetype As UInt32
Dim dbch_reserved As UInt32
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure DevBroadcastDeviceInterface
Dim dbcc_size As UInt32
Dim dbcc_devicetype As UInt32
Dim dbcc_reserved As UInt32
Dim dbcc_classguid As Guid
Dim dbcc_name As IntPtr
End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
Public Structure DevBroadcastVolume
Dim DBCV_Size As UInt32
Dim DBCV_DeviceType As UInt32
Dim DBCV_Reserved As UInt32
Dim DBCV_UnitMask As UInt32
Dim DBCV_Flags As UInt16
End Structure
<DllImport("user32.dll", ExactSpelling:=False, SetLastError:=True, CharSet:=CharSet.Unicode)> _
Private Shared Function RegisterDeviceNotification(ByVal hRecipient As IntPtr, _
ByRef NotificationFilter As DevBroadcastDeviceInterface, _
ByVal Flags As UInt32) As SafeDeviceNotificationHandle
End Function
Private Shared hDeviceNotify As SafeDeviceNotificationHandle = Nothing
Private Sub New()
End Sub
Public Shared Sub Start(ByVal hRecipient As IntPtr)
Dim dbd As DevBroadcastDeviceInterface = Nothing
If hDeviceNotify IsNot Nothing Then
UsbNotification.Cancel()
End If
dbd.dbcc_size = CUInt(Marshal.SizeOf(dbd))
dbd.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE
dbd.dbcc_classguid = New Guid("{A5DCBF10-6530-11D2-901F-00C04FB951ED}")
hDeviceNotify = RegisterDeviceNotification(hRecipient, dbd, 0)
If hDeviceNotify.IsInvalid Then
Debug.Print("Failed")
Else
Debug.Print("Register OK")
End If
End Sub
Public Shared Sub Cancel()
If hDeviceNotify IsNot Nothing Then
hDeviceNotify.Close()
hDeviceNotify.Dispose()
hDeviceNotify = Nothing
Debug.Print("UnRegister OK")
End If
End Sub
Public Shared Function GetDrive(ByVal UnitMask As UInteger) As String
GetDrive = Chr(CInt(65 + (Math.Log(UnitMask) / Math.Log(2))))
End Function
End Class
''' <summary>
''' Represents a wrapper class for a device notification handle.
''' </summary>
''' <remarks></remarks>
Public Class SafeDeviceNotificationHandle
Inherits SafeHandleZeroOrMinusOneIsInvalid
<DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True, CharSet:=CharSet.Unicode)> _
Private Shared Function UnregisterDeviceNotification(ByVal Handle As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private Sub New()
MyBase.New(True)
End Sub
Protected Overloads Overrides Function ReleaseHandle() As Boolean
Return UnregisterDeviceNotification(handle)
End Function
End Class
There is a couple of different ways you might get this information.
Using RegisterDeviceNotification
You won't need a loop because windows will broadcast the message to the WindowProc() so using this method would only require that you override WndProc() on your Form after registering the message.