How can i remove a USB flash disk programmatically using delphi?

前端 未结 3 1275
长情又很酷
长情又很酷 2020-12-28 09:45

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

3条回答
  •  春和景丽
    2020-12-28 10:10

    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()));
    

提交回复
热议问题