Как программно отключить флешку, чтобы исчезла иконка в трее и потухла лампочка на флешке? Максимум, что я добился, это отключение (disable, eject) устройства, при этом диск виден в проводнике, но при попытке его открытия пишет "Вставьте диск". Кто знает, как? Желательно на Builder'e, но пойдет и Delphi, и командная строка, и vbs. Блин, хоть как-нибудь... Перерыл уже весь интернет, перепробовал несколько способов.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
DiskName: TEdit;
btnEject: TButton;
Label1: TLabel;
procedure btnEjectClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
IOCTL_STORAGE_BASE = $0000002d;
FILE_READ_ACCESS = $0001;
FILE_ANY_ACCESS = $0000;
FILE_DEVICE_FILE_SYSTEM = $00000009;
METHOD_BUFFERED = 0;
IOCTL_STORAGE_MEDIA_REMOVAL = IOCTL_STORAGE_BASE shl 16 or
FILE_READ_ACCESS shl 14 or
$0201 shl 2 or METHOD_BUFFERED;
IOCTL_STORAGE_EJECT_MEDIA = IOCTL_STORAGE_BASE shl 16 or
FILE_READ_ACCESS shl 14 or
$0202 shl 2 or METHOD_BUFFERED;
FSCTL_LOCK_VOLUME = FILE_DEVICE_FILE_SYSTEM shl 16 or
FILE_ANY_ACCESS shl 14 or
6 shl 2 or METHOD_BUFFERED;
FSCTL_DISMOUNT_VOLUME = FILE_DEVICE_FILE_SYSTEM shl 16 or
FILE_ANY_ACCESS shl 14 or
8 shl 2 or METHOD_BUFFERED;
procedure TForm1.btnEjectClick(Sender: TObject);
var
dwBytesReturned: DWord;
hVolume: THandle;
PMRBuffer: Bool;
DevName : String;
begin
// Получаем полное имя диска
DevName:= Format('\\.\%s:', [DiskName.Text]);
// Открываем устройство
hVolume:= CreateFile(PChar(@DevName[1]), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
PMRBuffer := False;
If hVolume <> INVALID_HANDLE_VALUE then try
// Выдаем команды
If
DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, nil, 0, nil, 0, dwBytesReturned, nil) and
DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, nil, 0, nil, 0, dwBytesReturned, nil) and
DeviceIoControl(hVolume, IOCTL_STORAGE_MEDIA_REMOVAL, @PMRBuffer, sizeof(PMRBuffer), nil, 0, dwBytesReturned, nil) and
DeviceIoControl(hVolume, IOCTL_STORAGE_EJECT_MEDIA, nil, 0, nil, 0, dwBytesReturned, nil)
Then begin
ShowMessage('Устройство успешно извлечено');
End
Else begin
// Ошибка извлечения устройства
ShowMessage(SysErrorMessage(GetLastError))
End;
Finally
// Освободить дескриптор
CloseHandle(hVolume)
End
Else begin
// Ошибка открытия устройства
ShowMessage(SysErrorMessage(GetLastError));
End;
end;
end.
Pavel_Agurov, спасибо. Я так пробовал, но пишет ошибку, уже не помню какую, на команду IOCTL_STORAGE_MEDIA_REMOVAL.
В итоге сделал через setupapi. Вроде работает так, как надо.