有没有人知道在Windows 2000或更高版本上以编程方式关闭CD托盘的方法?打开CD托盘存在,但我似乎无法让它关闭,尤其是在W2k下.
我特别想找一种方法从批处理文件中执行此操作,如果可能的话,但API调用可以.
And*_*son 12
我有点喜欢使用DeviceIOControl,因为它可以弹出任何类型的可移动驱动器(例如USB和闪存盘以及CD托盘).使用DeviceIOControl正确弹出磁盘的Da codez(只需添加正确的错误处理):
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;
}
Run Code Online (Sandbox Code Playgroud)
以下是使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
我注意到安德烈亚斯·马格努森的回答与资源管理器的“弹出”按钮的工作原理并不完全相同。具体来说,使用 Andreas 的代码,驱动器在资源管理器中不会变灰,但如果您使用“弹出”命令,则驱动器会变灰。所以我做了一些调查。
我在从资源管理器(Windows 7 SP1 64 位)运行 Eject 命令时运行了 API Monitor。我还发现了一篇很好的(现已不存在的)MSKB 文章 165721,标题为“如何在 Windows NT/Windows 2000/Windows XP 中弹出可移动媒体”。文章中最有趣的部分引用如下:
- 使用 GENERIC_READ|GENERIC_WRITE、FILE_SHARE_READ|FILE_SHARE_WRITE 和 OPEN_EXISTING 调用 CreateFile。lpFileName 参数应为 \\.\X:(其中 X 是真实的驱动器号)。所有其他参数都可以为零。
- 通过 DeviceIoControl 发出 FSCTL_LOCK_VOLUME IOCTL 来锁定卷。如果任何其他应用程序或系统正在使用该卷,则此 IOCTL 失败。一旦该函数成功返回,应用程序就可以保证该卷不会被系统中的其他任何东西使用。
- 通过发出 FSCTL_DISMOUNT_VOLUME IOCTL 卸载卷。这会导致文件系统删除该卷的所有知识,并丢弃它保留的有关该卷的任何内部信息。
- 确保可以通过发出 IOCTL_STORAGE_MEDIA_REMOVAL IOCTL 来删除介质。在调用此 IOCTL 之前,将 PREVENT_MEDIA_REMOVAL 结构的 PreventMediaRemoval 成员设置为 FALSE。这会阻止设备阻止介质的移除。
- 使用 IOCTL_STORAGE_EJECT_MEDIA IOCTL 弹出媒体。如果设备不允许自动弹出,则可以跳过 IOCTL_STORAGE_EJECT_MEDIA,并指示用户移除介质。
- 关闭第一步中获得的卷句柄或发出 FSCTL_UNLOCK_VOLUME IOCTL。这允许其他进程使用该驱动器。
Andreas 的回答、MSKB 文章以及我对 Explorer 的 API 嗅探可以总结如下:
CreateFile调用以打开音量。(所有方法)。DeviceIoControl打电话给FSCTL_LOCK_VOLUME. (所有方法)。DeviceIoControl打电话给FSCTL_DISMOUNT_VOLUME. (仅限 Andreas 和 MSKB 方法。出于某种原因,Explorer 不会调用此方法。此 IOCTL 似乎会影响驱动器在 Explorer 中是否变灰。我不确定为什么 Explorer 不调用此方法)。DeviceIoControl调用IOCTL_STORAGE_MEDIA_REMOVAL并将PREVENT_MEDIA_REMOVAL成员设置为FALSE(MSKB 和 Explorer 方法。Andreas 的答案中缺少此步骤)。DeviceIoControl使用IOCTL_STORAGE_EJECT_MEDIA(Andreas 和 MSKB 文章)或IOCTL_DISK_EJECT_MEDIA(Explorer;注意此 IOCTL 已过时并被 STORAGE IOCTL 取代。不知道为什么 Explorer 仍然使用旧的)进行调用。最后,我决定遵循 MSKB 文章中概述的过程,因为它似乎是最彻底、最完整的过程,并有 MSKB 文章的支持。