How can I detect and remove a USB flash disk programatically using delphi?
I have seen some of the examples in this website, but they lack clear explanation on how t
This doesn't eject the drive, but it flushes the drive buffers and makes it safe to remove. It requires administrative rights under Vista and higher (and XP if running as a limited rights user, IIRC). It probably should have a try..finally to make sure that CloseHandle
gets called; I leave that as an exercise to the reader, since code formattig is tight here without horizontal scrolling. :-)
unit USBDriveFlush;
interface
uses Windows;
type
// Taken from JEDI JwaWinIoctl
PSTORAGE_HOTPLUG_INFO = ^STORAGE_HOTPLUG_INFO;
{$EXTERNALSYM PSTORAGE_HOTPLUG_INFO}
_STORAGE_HOTPLUG_INFO = record
Size: DWORD; // version
MediaRemovable: BOOLEAN; // ie. zip, jaz, cdrom, mo, etc. vs hdd
MediaHotplug: BOOLEAN; // ie. does the device succeed a lock
// even though its not lockable media?
DeviceHotplug: BOOLEAN; // ie. 1394, USB, etc.
WriteCacheEnableOverride: BOOLEAN; // This field should not be
// relied upon because it is no longer used
end;
{$EXTERNALSYM _STORAGE_HOTPLUG_INFO}
STORAGE_HOTPLUG_INFO = _STORAGE_HOTPLUG_INFO;
{$EXTERNALSYM STORAGE_HOTPLUG_INFO}
TStorageHotplugInfo = STORAGE_HOTPLUG_INFO;
PStorageHotplugInfo = PSTORAGE_HOTPLUG_INFO;
function FlushUSBDrive(const Drive: string): Boolean;
implementation
function FlushUSBDrive(const Drive: string): Boolean;
var
shpi : TStorageHotplugInfo;
retlen : DWORD; //unneeded, but deviceiocontrol expects it
h : THandle;
begin
Result := False;
h := CreateFile(PChar('\\.\' + Drive),
0,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
0,
0);
if h <> INVALID_HANDLE_VALUE then
begin
shpi.Size := SizeOf(shpi);
if DeviceIoControl(h,
IOCTL_STORAGE_GET_HOTPLUG_INFO,
nil,
0,
@shpi,
SizeOf(shpi),
retlen,
nil) then
begin
//shpi now has the existing values, so you can check to
//see if the device is already hot-pluggable
if not shpi.DeviceHotplug then
begin
shpi.DeviceHotplug:= True;
//Need to use correct administrator security privilages here
//otherwise it'll just give 'access is denied' error
Result := DeviceIoControl(h,
IOCTL_STORAGE_SET_HOTPLUG_INFO,
@shpi,
SizeOf(shpi),
nil,
0,
retlen,
nil);
end;
end;
CloseHandle(h);
end;
end;
Sample use:
if FlushUSBDrive('G:') then
ShowMessage('Safe to remove USB drive G:')
else
ShowMessage('Flush of drive G: failed!' +
SysErrorMessage(GetLastError()));