Start a action when a USB device is added [duplicate]
I try to start an application, when a special USB device is added.
In the windows event system I can use the event:
Microsoft-Windows-DriverFrameworks-UserMode
-> Event ID: 2100
This event is raised, when a new device is added. This works fine, but I will find out which drive was added.
Within the event system I found, that additional information is available, but how I can use this information?
Is it possible to get the information, which drive was added? Or is it possible to hand over the additional data of the event system to a user program (command line parameter)?
Solution 1:
I don't know how you could do this without programming, but I've written applications that do exactly what you want. So here's how to implement it.
When a new device is added to the system (like a USB drive), Windows sends out the WM_DEVICECHANGE
message to all top-level application windows. The event to look for is DBT_DEVICEARRIVAL
(which is indicated through the wParam
of that message).
The lParam
of the message should first be treated as a DEV_BROADCAST_HDR
. The header will indicate (through it's dbch_devicetype
member) if the device is actually a volume (DBT_DEVTYP_VOLUME
). If it is a volume, you can reinterpret the lParam
of the original message as a DEV_BROADCAST_VOLUME
. This structure will then indicate the assigned drive letters through the dbcv_unitmask
member.
To make it (hopefully) a bit clearer, here's some working code from an implementation of mine in C#:
private static void MessageEventsMessageReceived( object sender, MessageReceivedEventArgs e ) {
// Check if this is a notification regarding a new device.);
if( e.Message.WParam == (IntPtr)NativeMethods.DBT_DEVICEARRIVAL ) {
Log.Info( "New device has arrived" );
// Retrieve the device broadcast header
NativeMethods.DEV_BROADCAST_HDR deviceBroadcastHeader =
(NativeMethods.DEV_BROADCAST_HDR)
Marshal.PtrToStructure( e.Message.LParam, typeof( NativeMethods.DEV_BROADCAST_HDR ) );
if( (int)NativeMethods.DBT_DEVTYP.DBT_DEVTYP_VOLUME == deviceBroadcastHeader.dbch_devicetype ) {
Log.Info( "Device type is a volume (good)." );
NativeMethods.DEV_BROADCAST_VOLUME volumeBroadcast =
(NativeMethods.DEV_BROADCAST_VOLUME)
Marshal.PtrToStructure( e.Message.LParam, typeof( NativeMethods.DEV_BROADCAST_VOLUME ) );
Log.InfoFormat( "Unit masked for new device is: {0}", volumeBroadcast.dbcv_unitmask );
int driveIndex = 1;
int bitCount = 1;
while( bitCount <= 0x2000000 ) {
driveIndex++;
bitCount *= 2;
if( ( bitCount & volumeBroadcast.dbcv_unitmask ) != 0 ) {
Log.InfoFormat( "Drive index {0} is set in unit mask.", driveIndex );
Log.InfoFormat( "Device provides drive: {0}:", (char)( driveIndex + 64 ) );
int index = driveIndex;
char driveLetter = (char)( driveIndex + 64 );
// Do something with driveLetter
}
}
} else {
Log.InfoFormat( "Device type is {0} (ignored).", Enum.GetName( typeof( NativeMethods.DBT_DEVTYP ), deviceBroadcastHeader.dbch_devicetype ) );
}
}
}