Here is the code that works for me, which is part of the site above combined with my early tests: http://www.codeproject.com/KB/system/DriveDetector.aspx
This basically makes your form listen for Windows messages, filters for USB drives and (cd-dvds), grabs the lparam structure of the message and extracts the drive letter.
protected override void WndProc(ref Message m) { if (m.Msg == WM_DEVICECHANGE) { DEV_BROADCAST_VOLUME vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME)); if ((m.WParam.ToInt32() == DBT_DEVICEARRIVAL) && (vol.dbcv_devicetype == DBT_DEVTYPVOLUME) ) { MessageBox.Show(DriveMaskToLetter(vol.dbcv_unitmask).ToString()); } if ((m.WParam.ToInt32() == DBT_DEVICEREMOVALCOMPLETE) && (vol.dbcv_devicetype == DBT_DEVTYPVOLUME)) { MessageBox.Show("usb out"); } } base.WndProc(ref m); } [StructLayout(LayoutKind.Sequential)] //Same layout in mem public struct DEV_BROADCAST_VOLUME { public int dbcv_size; public int dbcv_devicetype; public int dbcv_reserved; public int dbcv_unitmask; } private static char DriveMaskToLetter(int mask) { char letter; string drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //1 = A, 2 = B, 3 = C int cnt = 0; int pom = mask / 2; while (pom != 0) // while there is any bit set in the mask shift it right { pom = pom / 2; cnt++; } if (cnt < drives.Length) letter = drives[cnt]; else letter = '?'; return letter; }
Remember to add this:
using System.Runtime.InteropServices;
and the following constants:
const int WM_DEVICECHANGE = 0x0219; //see msdn site const int DBT_DEVICEARRIVAL = 0x8000; const int DBT_DEVICEREMOVALCOMPLETE = 0x8004; const int DBT_DEVTYPVOLUME = 0x00000002;
Onsightfree Oct 17 '12 at 11:09 2012-10-17 11:09
source share