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

时间:2009-05-16 17:53:37

标签: windows delphi

我试过这段代码:

uses MMSystem;

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

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

但没有效果。我听说这不适用于所有系统。

我正试图让驱动器在Windows XP上弹出,并希望通过驱动器号指定驱动器(对于具有多个驱动器的系统是必需的)。

2 个答案:

答案 0 :(得分:10)

这是使用 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;

忽略错误处理。

答案 1 :(得分:2)


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;

编辑:如您所见,我没有编写任何错误处理代码。如果指定了无效的驱动器,此代码将引发异常。