We help IT Professionals succeed at work.
Get Started

Improve code for detecting USB drive insertion & removal

WinRat
WinRat asked
on
6,755 Views
Last Modified: 2012-06-21
Dear Experts,
Please refer to the included code which detects when a USB device is connected or disconnected.
It worked perfectly for me. As you can see it handles the Windows message WM_DEVICECHANGE.
However as it stands its not that flexible for easily adding to a project..

It would be nice to have this in a self-contained unit that generates suitable events when a USB device is attached or removed. I would prefer that it not be made into a component that I have to install, in order  to produce more portable code.

I don't know if its possible to handle a message without a form, but maybe it could be a small non-visible dummy form.

If it seems possible I would appreciate a working Delphi 5 compatible version.
Many thanks!

unit USBDetectF;
{taken from an Experts Exchange solution:
 http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/
                             Q_21552015.html?sfQueryTermInfo=1+drive+letter+usb
 ginsonic:
 Here is a complete sample project. Use a form and a label.
}
 
interface
 
uses
  Windows, Messages, Classes, Forms, Controls, StdCtrls, Buttons;
 
type
  TUSBDetectForm = class(TForm)
    Label1: TLabel;
    BitBtn1: TBitBtn;
    Label2: TLabel;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  protected
    procedure   WMDEVICECHANGE(var Msg: TMessage); message WM_DEVICECHANGE;
  public
    { Public declarations }
  end;
 
var
  USBDetectForm: TUSBDetectForm;
 
{----------------------------------------------------------------------------}
// Device constants
const
  DBT_DEVICEARRIVAL          =  $00008000;
  DBT_DEVICEREMOVECOMPLETE   =  $00008004;
  DBT_DEVTYP_VOLUME          =  $00000002;
 
// Device structs
type
  _DEV_BROADCAST_HDR         =  packed record
     dbch_size:              DWORD;
     dbch_devicetype:        DWORD;
     dbch_reserved:          DWORD;
  end;
  DEV_BROADCAST_HDR          =  _DEV_BROADCAST_HDR;
  TDevBroadcastHeader        =  DEV_BROADCAST_HDR;
  PDevBroadcastHeader        =  ^TDevBroadcastHeader;
 
type
  _DEV_BROADCAST_VOLUME      =  packed record
     dbch_size:              DWORD;
     dbch_devicetype:        DWORD;
     dbch_reserved:          DWORD;
     dbcv_unitmask:          DWORD;
     dbcv_flags:             WORD;
  end;
  DEV_BROADCAST_VOLUME       =  _DEV_BROADCAST_VOLUME;
  TDevBroadcastVolume        =  DEV_BROADCAST_VOLUME;
  PDevBroadcastVolume        =  ^TDevBroadcastVolume;
 
implementation
{$R *.dfm}
 
procedure TUSBDetectForm.WMDEVICECHANGE(var Msg: TMessage);
var  lpdbhHeader:   PDevBroadcastHeader;
     lpdbvData:     PDevBroadcastVolume;
     dwIndex:       Integer;
     lpszDrive:      String;
begin
 
  // Perform inherited
  inherited;
 
  // Get the device notification header
  lpdbhHeader:=PDevBroadcastHeader(Msg.lParam);
 
  // Handle the message
  lpszDrive:='Drive ';
  case Msg.WParam of
     DBT_DEVICEARRIVAL       :    {a USB drive was connected}
     begin
        if (lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME) then
        begin
           lpdbvData:=PDevBroadcastVolume(Msg.lParam);
           for dwIndex :=0 to 25 do
           begin
              if ((lpdbvData^.dbcv_unitmask shr dwIndex) = 1) then
              begin
                 lpszDrive:=lpszDrive+Chr(65+dwIndex)+':';
                 break;
              end;
           end;
           Label1.Caption:=lpszDrive + ' connected';
        end;
     end;
     DBT_DEVICEREMOVECOMPLETE:    {a USB drive was removed}
     begin
        if (lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME) then
        begin
           lpdbvData:=PDevBroadcastVolume(Msg.lParam);
           for dwIndex:=0 to 25 do
           begin
              if ((lpdbvData^.dbcv_unitmask shr dwIndex) = 1) then
              begin
                 lpszDrive:=lpszDrive+Chr(65+dwIndex)+':';
                 break;
              end;
           end;
           Label1.Caption:=lpszDrive + ' removed';
        end;
     end;
  end;
end;
 
procedure TUSBDetectForm.FormCreate(Sender: TObject);
begin
  Label1.Caption := '';
end;
 
end.

Open in new window

Comment
Watch Question
Oracle dba
CERTIFIED EXPERT
Top Expert 2009
Commented:
This problem has been solved!
Unlock 1 Answer and 4 Comments.
See Answer
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE