11

有谁知道在 Windows 2000 或更高版本上以编程方式关闭 CD 托盘的方法?存在打开的 CD 托盘,但我似乎无法将其关闭,尤其是在 W2k 下。

如果可能的话,我特别在寻找一种从批处理文件中执行此操作的方法,但是 API 调用就可以了。

4

5 回答 5

14

我有点喜欢使用 DeviceIOControl,因为它让我可以弹出任何类型的可移动驱动器(例如 USB 和闪存盘以及 CD 托盘)。使用 DeviceIOControl 正确弹出磁盘的代码是(只需添加正确的错误处理):

bool ejectDisk(TCHAR driveLetter)
{
  TCHAR tmp[10];
  _stprintf(tmp, _T("\\\\.\\%c:"), driveLetter);
  HANDLE handle = CreateFile(tmp, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
  DWORD bytes = 0;
  DeviceIoControl(handle, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &bytes, 0);
  DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &bytes, 0);
  DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &bytes, 0);
  CloseHandle(handle);
  return true;
}
于 2008-09-16T21:24:35.067 回答
8

这是使用 Win32 API 的简单方法:


[DllImport("winmm.dll", EntryPoint = "mciSendStringA", CharSet = CharSet.Ansi)]
        protected static extern int mciSendString(string lpstrCommand,StringBuilder lpstrReturnString,int uReturnLength,IntPtr hwndCallback);

 public void OpenCloseCD(bool Open)
 {
    if (Open)
    {
        mciSendString("set cdaudio door open", null, 0, IntPtr.Zero);
    }
    else
    {
        mciSendString("set cdaudio door closed", null, 0, IntPtr.Zero);
    }
}

于 2008-09-12T11:28:03.583 回答
4

我注意到 Andreas Magnusson 的回答与 Explorer 的“弹出”按钮的作用并不完全相同。具体来说,使用 Andreas 的代码在 Explorer 中驱动器没有灰显,但如果您使用了 Eject 命令,驱动器就会灰显。所以我做了一些调查。

我在从资源管理器(Windows 7 SP1 64 位)运行 Eject 命令时运行了 API Monitor。我还发现了一篇很好的(现已失效的)MSKB 文章 165721,标题为How To Ejecting Removable Media in Windows NT/Windows 2000/Windows XP。文章中最有趣的部分引述如下:

  1. 使用 GENERIC_READ|GENERIC_WRITE、FILE_SHARE_READ|FILE_SHARE_WRITE 和 OPEN_EXISTING 调用 CreateFile。lpFileName 参数应该是 \\.\X: (其中 X 是真正的驱动器号)。所有其他参数都可以为零。
  2. 通过 DeviceIoControl 发出 FSCTL_LOCK_VOLUME IOCTL 来锁定卷。如果任何其他应用程序或系统正在使用该卷,则此 IOCTL 将失败。一旦这个函数成功返回,应用程序就可以保证该卷不被系统中的任何其他东西使用。
  3. 通过发出 FSCTL_DISMOUNT_VOLUME IOCTL 卸载卷。这会导致文件系统删除有关该卷的所有信息,并丢弃它保留的有关该卷的任何内部信息。
  4. 确保可以通过发出 IOCTL_STORAGE_MEDIA_REMOVAL IOCTL 来删除媒体。在调用此 IOCTL 之前,将 PREVENT_MEDIA_REMOVAL 结构的 PreventMediaRemoval 成员设置为 FALSE。这会阻止设备阻止媒体被移除。
  5. 使用 IOCTL_STORAGE_EJECT_MEDIA IOCTL 弹出媒体。如果设备不允许自动弹出,则可以跳过 IOCTL_STORAGE_EJECT_MEDIA 并指示用户移除媒体。
  6. 关闭第一步获得的卷句柄或发出 FSCTL_UNLOCK_VOLUME IOCTL。这允许驱动器被其他进程使用。

Andreas 的回答,MSKB 的文章,以及我对 Explorer 的 API 嗅探,可以总结如下:

  1. CreateFile调用打开卷。(所有方法)。
  2. DeviceIoControl用 调用FSCTL_LOCK_VOLUME。(所有方法)。
  3. DeviceIoControl用 调用FSCTL_DISMOUNT_VOLUME。(仅限 Andreas 和 MSKB 方法。资源管理器由于某种原因不会调用它。这个 IOCTL 似乎是影响驱动器在资源管理器中是否变灰的原因。我不确定资源管理器为什么不调用它)。
  4. DeviceIoControl调用IOCTL_STORAGE_MEDIA_REMOVALPREVENT_MEDIA_REMOVAL成员设置为FALSE(MSKB 和资源管理器方法。安德烈亚斯的答案中缺少此步骤)。
  5. DeviceIoControl使用IOCTL_STORAGE_EJECT_MEDIA(Andreas 和 MSKB 文章)或IOCTL_DISK_EJECT_MEDIA(Explorer;请注意此 IOCTL 已过时并替换为 STORAGE IOCTL。不确定为什么 Explorer 仍使用旧的)调用。

最后,我决定遵循 MSKB 文章中概述的程序,因为它似乎是最彻底和最完整的程序,并以 MSKB 文章为后盾。

于 2015-05-28T17:11:26.633 回答
2

Nircmd是一个非常方便的免费命令行实用程序,具有多种选项,包括打开和关闭 CD 托盘。

于 2008-09-12T10:58:03.017 回答
1

要关闭驱动器托盘,请按照此处所述进行操作,但不要将 DeviceIoControl 与 IOCTL_STORAGE_EJECT_MEDIA 一起使用,您需要使用 IOCTL_STORAGE_LOAD_MEDIA 调用 DeviceIoControl。

于 2015-09-03T09:14:06.753 回答