简体   繁体   English

Delphi:如何使用驱动器号以编程方式弹出CD

[英]Delphi: How to programmatically eject a CD using the drive letter

I have tried this code: 我试过这段代码:

uses MMSystem;

mciSendString('Set cdaudio door open wait', nil, 0, handle);

mciSendString('Set cdaudio door closed wait', nil, 0, handle);

but there was no effect. 但是没有效果。 I have heard that this does not work on all systems. 我听说这不适用于所有系统。

I'm trying to get a drive to eject on Windows XP, and would like to specify the drive via the drive letter (necessary for systems with multiple drives). 我正试图让驱动器在Windows XP上弹出,并希望通过驱动器号指定驱动器(对于具有多个驱动器的系统是必需的)。

This is code using the DeviceIOControl() API function, works for me on Windows XP (compiled and tested using Delphi 5): 这是使用DeviceIOControl() API函数的代码,适用于Windows XP(使用Delphi 5编译和测试):

function DeviceIOControlHelper(ADeviceHandle: THandle;
  ADeviceIOControlCode: DWORD): boolean;
var
  BytesReturned: Cardinal;
begin
  Result := DeviceIOControl(ADeviceHandle, ADeviceIOControlCode,
    nil, 0, nil, 0, BytesReturned, nil);
end;

function SetDriveDoorOpen(ADriveLetter: char; AValue: boolean): boolean;
const
  FILE_DEVICE_FILE_SYSTEM = 9;
  FILE_ANY_ACCESS = 0;
  FILE_READ_ACCESS = 1;
  METHOD_BUFFERED = 0;
  IOCTL_STORAGE_BASE = $2D;

(*
#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
*)

//  FSCTL_LOCK_VOLUME = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6,
//                               METHOD_BUFFERED, FILE_ANY_ACCESS);
  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 = CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8,
//                                   METHOD_BUFFERED, FILE_ANY_ACCESS);
  FSCTL_DISMOUNT_VOLUME = (FILE_DEVICE_FILE_SYSTEM shl 16)
                          or (FILE_ANY_ACCESS shl 14)
                          or (8 shl 2) or METHOD_BUFFERED;
//  IOCTL_STORAGE_EJECT_MEDIA = CTL_CODE(IOCTL_STORAGE_BASE, 0x0202,
//                                       METHOD_BUFFERED, FILE_READ_ACCESS);
  IOCTL_STORAGE_EJECT_MEDIA = (IOCTL_STORAGE_BASE shl 16)
                              or (FILE_READ_ACCESS shl 14)
                              or ($0202 shl 2) or METHOD_BUFFERED;
//  IOCTL_STORAGE_LOAD_MEDIA = CTL_CODE(IOCTL_STORAGE_BASE, 0x0203,
//                                      METHOD_BUFFERED, FILE_READ_ACCESS);
  IOCTL_STORAGE_LOAD_MEDIA = (IOCTL_STORAGE_BASE shl 16)
                              or (FILE_READ_ACCESS shl 14)
                              or ($0203 shl 2) or METHOD_BUFFERED;
var
  DriveCmdStr: string;
  DriveHandle: THandle;
begin
  Result := FALSE;
  DriveCmdStr := Format('\\.\%s:', [ADriveLetter]);
  DriveHandle := CreateFile(PChar(DriveCmdStr), GENERIC_READ, FILE_SHARE_WRITE,
    nil, OPEN_EXISTING, 0, 0);
  if DriveHandle <> INVALID_HANDLE_VALUE then begin
    if AValue then begin
      Result := DeviceIOControlHelper(DriveHandle, FSCTL_LOCK_VOLUME)
        and DeviceIOControlHelper(DriveHandle, FSCTL_DISMOUNT_VOLUME)
        and DeviceIOControlHelper(DriveHandle, IOCTL_STORAGE_EJECT_MEDIA);
    end else
      Result := DeviceIOControlHelper(DriveHandle, IOCTL_STORAGE_LOAD_MEDIA);
    CloseHandle(DriveHandle);
  end;
end;

Error handling omitted. 错误处理省略。


uses ComObj;

function EjectDrive(const ADriveLetter: string): Boolean;
var
  WMP: Variant;
  CDROMs: Variant;
  Drive: Variant;
begin
  WMP := CreateOleObject('WMPlayer.OCX.7');
  CDROMs := WMP.CDROMCollection;
  Drive := CDROMs.GetByDriveSpecifier(ADriveLetter + ':');
  Drive.Eject;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  EjectDrive('Q');
end;

Edit: As you can see, I didn't write any error handling code. 编辑:如您所见,我没有写任何错误处理代码。 This code will raise an exception if an invalid drive is specified. 如果指定了无效的驱动器,此代码将引发异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM