In this post i am going to explain some more interesting thing, USB Detector so this article deals with create a application for detect the USB when inserted and removed from computer and make a notification to user on removal
USB Detector :
Click Here To Download
Launch the application after the download, Then plug in the USB device in the computer now you will see a device add in the application and select a Notify checkbox to notify the user when it is try to remove
Now we see how to do this application.
USBDetector:
public class USBDetector
: IDisposable
{
public event USBDetectorEventHandler
DeviceArrived;
public event USBDetectorEventHandler
DeviceRemoved;
public event USBDetectorEventHandler
QueryRemove;
public
USBDetector()
{
DriveForm
frm = new DriveForm(this);
frm.Show();
Init(frm, null);
}
public
USBDetector(Control control)
{
Init(control, null);
}
public
USBDetector(Control control, string FileToOpen)
{
Init(control, FileToOpen);
}
private
void Init(Control
control, string fileToOpen)
{
mFileToOpen = fileToOpen;
mFileOnFlash = null;
mDeviceNotifyHandle = IntPtr.Zero;
mRecipientHandle = control.Handle;
mDirHandle = IntPtr.Zero;
mCurrentDrive = "";
}
public bool IsQueryHooked
{
get
{
if
(mDeviceNotifyHandle == IntPtr.Zero)
return
false;
else
return
true;
}
}
public string HookedDrive
{
get
{
return
mCurrentDrive;
}
}
public FileStream OpenedFile
{
get
{
return
mFileOnFlash;
}
}
public bool EnableQueryRemove(string
fileOnDrive)
{
if
(fileOnDrive == null || fileOnDrive.Length ==
0)
throw
new ArgumentException("Drive path must be supplied to register for Query
remove.");
if
(fileOnDrive.Length == 2 && fileOnDrive[1] == ':')
fileOnDrive += '\\';
// append "\\" if only drive letter
with ":" was passed in.
if
(mDeviceNotifyHandle != IntPtr.Zero)
{
//
Unregister first...
RegisterForDeviceChange(false, null);
}
if
(Path.GetFileName(fileOnDrive).Length == 0
|| !File.Exists(fileOnDrive))
mFileToOpen = null; // use root directory...
else
mFileToOpen = fileOnDrive;
RegisterQuery(Path.GetPathRoot(fileOnDrive));
if
(mDeviceNotifyHandle == IntPtr.Zero)
return
false; // failed to register
return
true;
}
public
void DisableQueryRemove()
{
if
(mDeviceNotifyHandle != IntPtr.Zero)
{
RegisterForDeviceChange(false, null);
}
}
public void Dispose()
{
RegisterForDeviceChange(false, null);
}
#region WindowProc
public void WndProc(ref Message m)
{
int
devType;
char
c;
if
(m.Msg == WM_DEVICECHANGE)
{
switch
(m.WParam.ToInt32())
{
case
DBT_DEVICEARRIVAL:
devType = Marshal.ReadInt32(m.LParam, 4);
if (devType == DBT_DEVTYP_VOLUME)
{
DEV_BROADCAST_VOLUME vol;
vol = (DEV_BROADCAST_VOLUME)
Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
c =
DriveMaskToLetter(vol.dbcv_unitmask);
USBDetectorEventHandler tempDeviceArrived =
DeviceArrived;
if (tempDeviceArrived != null)
{
USBDetectorEventArgs e = new
USBDetectorEventArgs();
e.Drive = c + ":\\";
tempDeviceArrived(this, e);
// Register for query remove if requested
if (e.HookQueryRemove)
{
// If something is already hooked, unhook it now
if (mDeviceNotifyHandle != IntPtr.Zero)
{
RegisterForDeviceChange(false, null);
}
RegisterQuery(c + ":\\");
}
} // if has event handler
}
break;
case
DBT_DEVICEQUERYREMOVE:
devType = Marshal.ReadInt32(m.LParam, 4);
if (devType == DBT_DEVTYP_HANDLE)
{
USBDetectorEventHandler tempQuery = QueryRemove;
if (tempQuery != null)
{
USBDetectorEventArgs e = new
USBDetectorEventArgs();
e.Drive =
mCurrentDrive; // drive which is hooked
tempQuery(this, e);
// If the client wants to cancel, let Windows know
if (e.Cancel)
{
m.Result =
(IntPtr)BROADCAST_QUERY_DENY;
}
else
{
RegisterForDeviceChange(false, null); // will also close
the mFileOnFlash
}
}
}
break;
//
//
Device has been removed
//
case
DBT_DEVICEREMOVECOMPLETE:
devType = Marshal.ReadInt32(m.LParam, 4);
if (devType == DBT_DEVTYP_VOLUME)
{
devType = Marshal.ReadInt32(m.LParam,
4);
if (devType == DBT_DEVTYP_VOLUME)
{
DEV_BROADCAST_VOLUME vol;
vol = (DEV_BROADCAST_VOLUME)
Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
c =
DriveMaskToLetter(vol.dbcv_unitmask);
//
// Call the
client event handler
//
USBDetectorEventHandler tempDeviceRemoved =
DeviceRemoved;
if (tempDeviceRemoved != null)
{
USBDetectorEventArgs e = new
USBDetectorEventArgs();
e.Drive = c
+ ":\\";
tempDeviceRemoved(this, e);
}
}
}
break;
}
}
}
#endregion
#region
Private Area
private
IntPtr mDirHandle = IntPtr.Zero;
private
FileStream mFileOnFlash = null;
private
string mFileToOpen;
private
IntPtr mDeviceNotifyHandle;
private
IntPtr mRecipientHandle;
private
string mCurrentDrive;
private
const int
DBT_DEVTYP_DEVICEINTERFACE = 5;
private
const int
DBT_DEVTYP_HANDLE = 6;
private
const int
BROADCAST_QUERY_DENY = 0x424D5144;
private
const int
WM_DEVICECHANGE = 0x0219;
private
const int
DBT_DEVICEARRIVAL = 0x8000; // system detected a new
device
private
const int
DBT_DEVICEQUERYREMOVE = 0x8001; // Preparing to remove (any program can disable the
removal)
private
const int
DBT_DEVICEREMOVECOMPLETE = 0x8004; // removed
private
const int
DBT_DEVTYP_VOLUME = 0x00000002; // drive type is
logical volume
private
void RegisterQuery(string
drive)
{
bool
register = true;
if
(mFileToOpen == null)
{
}
else
{
if
(mFileToOpen.Contains(":"))
{
string
tmp = mFileToOpen.Substring(3);
string
root = Path.GetPathRoot(drive);
mFileToOpen = Path.Combine(root, tmp);
}
else
mFileToOpen = Path.Combine(drive, mFileToOpen);
}
try
{
if
(mFileToOpen == null) // open root
directory
mFileOnFlash = null;
else
mFileOnFlash = new FileStream(mFileToOpen,
FileMode.Open);
}
catch
(Exception)
{
//
just do not register if the file could not be opened
register = false;
}
if
(register)
{
if
(mFileOnFlash == null)
RegisterForDeviceChange(drive);
else
//
old version
RegisterForDeviceChange(true, mFileOnFlash.SafeFileHandle);
mCurrentDrive = drive;
}
}
private
void RegisterForDeviceChange(string dirPath)
{
IntPtr
handle = Native.OpenDirectory(dirPath);
if
(handle == IntPtr.Zero)
{
mDeviceNotifyHandle = IntPtr.Zero;
return;
}
else
mDirHandle = handle; // save handle
for closing it when unregistering
//
Register for handle
DEV_BROADCAST_HANDLE
data = new DEV_BROADCAST_HANDLE();
data.dbch_devicetype =
DBT_DEVTYP_HANDLE;
data.dbch_reserved = 0;
data.dbch_nameoffset = 0;
//data.dbch_data
= null;
//data.dbch_eventguid
= 0;
data.dbch_handle = handle;
data.dbch_hdevnotify = (IntPtr)0;
int
size = Marshal.SizeOf(data);
data.dbch_size = size;
IntPtr
buffer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(data,
buffer, true);
mDeviceNotifyHandle = Native.RegisterDeviceNotification(mRecipientHandle,
buffer, 0);
}
private
void RegisterForDeviceChange(bool register, SafeFileHandle
fileHandle)
{
if
(register)
{
//
Register for handle
DEV_BROADCAST_HANDLE
data = new DEV_BROADCAST_HANDLE();
data.dbch_devicetype =
DBT_DEVTYP_HANDLE;
data.dbch_reserved = 0;
data.dbch_nameoffset = 0;
//data.dbch_data
= null;
//data.dbch_eventguid
= 0;
data.dbch_handle =
fileHandle.DangerousGetHandle(); //Marshal.
fileHandle;
data.dbch_hdevnotify = (IntPtr)0;
int
size = Marshal.SizeOf(data);
data.dbch_size = size;
IntPtr
buffer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(data,
buffer, true);
mDeviceNotifyHandle = Native.RegisterDeviceNotification(mRecipientHandle,
buffer, 0);
}
else
{
// close the
directory handle
if
(mDirHandle != IntPtr.Zero)
{
Native.CloseDirectoryHandle(mDirHandle);
// string er =
Marshal.GetLastWin32Error().ToString();
}
// unregister
if
(mDeviceNotifyHandle != IntPtr.Zero)
{
Native.UnregisterDeviceNotification(mDeviceNotifyHandle);
}
mDeviceNotifyHandle = IntPtr.Zero;
mDirHandle = IntPtr.Zero;
mCurrentDrive = "";
if
(mFileOnFlash != null)
{
mFileOnFlash.Close();
mFileOnFlash = null;
}
}
}
private
static char
DriveMaskToLetter(int mask)
{
char
letter;
string
drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 1 = A
// 2 = B
// 4 =
C...
int
cnt = 0;
int
pom = mask / 2;
while
(pom != 0)
{
//
while there is any bit set in the mask
//
shift it to the righ...
pom = pom / 2;
cnt++;
}
if
(cnt < drives.Length)
letter = drives[cnt];
else
letter = '?';
return
letter;
}
#endregion
#region Native Win32 API
/// <summary>
/// WinAPI functions
/// </summary>
private
class Native
{
// HDEVNOTIFY RegisterDeviceNotification(HANDLE
hRecipient,LPVOID NotificationFilter,DWORD Flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public
static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr
NotificationFilter, uint Flags);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public
static extern uint UnregisterDeviceNotification(IntPtr hHandle);
//
//
CreateFile - MSDN
const
uint GENERIC_READ = 0x80000000;
const
uint OPEN_EXISTING = 3;
const
uint FILE_SHARE_READ = 0x00000001;
const
uint FILE_SHARE_WRITE = 0x00000002;
const
uint FILE_ATTRIBUTE_NORMAL = 128;
const
uint FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
static
readonly IntPtr
INVALID_HANDLE_VALUE = new IntPtr(-1);
// should
be "static extern unsafe"
[DllImport("kernel32", SetLastError = true)]
static
extern IntPtr
CreateFile(
string
FileName, // file name
uint
DesiredAccess, // access mode
uint
ShareMode, // share mode
uint
SecurityAttributes, // Security Attributes
uint
CreationDisposition, // how to create
uint
FlagsAndAttributes, // file attributes
int
hTemplateFile // handle to template file
);
[DllImport("kernel32", SetLastError = true)]
static
extern bool
CloseHandle(
IntPtr
hObject //
handle to object
);
/// <summary>
/// Opens a directory, returns it's handle or zero.
/// </summary>
/// <param
name="dirPath">path to the
directory, e.g. "C:\\dir"</param>
/// <returns>handle to the directory. Close it with CloseHandle().</returns>
static
public IntPtr
OpenDirectory(string dirPath)
{
//
open the existing file for reading
IntPtr
handle = CreateFile(
dirPath,
GENERIC_READ,
FILE_SHARE_READ |
FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS |
FILE_ATTRIBUTE_NORMAL,
0);
if
(handle == INVALID_HANDLE_VALUE)
return
IntPtr.Zero;
else
return
handle;
}
public
static bool
CloseDirectoryHandle(IntPtr handle)
{
return
CloseHandle(handle);
}
}
// Structure
with information for RegisterDeviceNotification.
[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_HANDLE
{
public
int dbch_size;
public
int dbch_devicetype;
public
int dbch_reserved;
public
IntPtr dbch_handle;
public
IntPtr dbch_hdevnotify;
public
Guid dbch_eventguid;
public
long dbch_nameoffset;
//public
byte[] dbch_data[1]; // = new byte[1];
public
byte dbch_data;
public
byte dbch_data1;
}
// Struct for
parameters of the WM_DEVICECHANGE message
[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_VOLUME
{
public
int dbcv_size;
public
int dbcv_devicetype;
public
int dbcv_reserved;
public
int dbcv_unitmask;
}
#endregion
}
UsbDetectorEventArgs
using System;
using
System.Collections.Generic;
using System.Linq;
using System.Text;
namespace USB_Detector
{
// Delegate for event handler to handle the
device events
public delegate
void USBDetectorEventHandler(Object sender, USBDetectorEventArgs
e);
/// <summary>
/// Our class
for passing in custom arguments to our event handlers
///
/// </summary>
public class
USBDetectorEventArgs : EventArgs
{
public
USBDetectorEventArgs()
{
Cancel = false;
Drive = "";
HookQueryRemove = false;
}
/// <summary>
/// Get/Set the value indicating that the event should be
cancelled
/// Only in QueryRemove handler.
/// </summary>
public bool Cancel;
/// <summary>
/// Drive letter for the device which caused this event
/// </summary>
public string Drive;
/// <summary>
/// Set to true in your DeviceArrived event handler if you
wish to receive the
/// QueryRemove event for this drive.
/// </summary>
public bool HookQueryRemove;
}
}
Now create a Form which is invisble at runtime because we need a WndProc to get the Notification from the Native OS.
public partial class DriveForm : Form
{
public
DriveForm()
{
}
private Label
label1;
private USBDetector
mDetector = null;
/// <summary>
/// Set up the hidden form.
/// </summary>
/// <param name="detector">DriveDetector object which will receive notification about
USB drives, see WndProc</param>
public DriveForm(USBDetector
detector)
{
mDetector = detector;
this.MinimizeBox = false;
this.MaximizeBox = false;
this.ShowInTaskbar = false;
this.ShowIcon = false;
this.FormBorderStyle = FormBorderStyle.None;
this.Load += new
System.EventHandler(this.Load_Form);
this.Activated += new
EventHandler(this.Form_Activated);
}
/// <summary>
/// This function receives
all the windows messages for this window (form).
/// We call the
DriveDetector from here so that is can pick up the messages about
/// drives arrived and removed.
/// </summary>
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (mDetector != null)
{
mDetector.WndProc(ref m);
}
}
private void
Load_Form(object sender, EventArgs e)
{
InitializeComponent();
this.Size = new
System.Drawing.Size(5, 5);
}
private void
Form_Activated(object sender, EventArgs e)
{
this.Visible = false;
}
}
From this article you will get some interesting tool to get notify for portable devices plug in computer.