Windows光盘弹出

Windows光盘弹出,windows,winapi,Windows,Winapi,有人知道在Windows 2000或更高版本上以编程方式关闭CD托槽的方法吗? 开放式CD托盘存在,但我似乎无法将其关闭,尤其是在W2k下 如果可能的话,我特别想从批处理文件中寻找一种方法来实现这一点,但是API调用也可以。是一个非常方便的免费命令行实用程序,具有各种选项,包括打开和关闭CD托盘。下面是一个使用Win32 API的简单方法: [DllImport("winmm.dll", EntryPoint = "mciSendStringA", CharSet = CharSet.Ansi

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


如果可能的话,我特别想从批处理文件中寻找一种方法来实现这一点,但是API调用也可以。

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

下面是一个使用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);
    }
}


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


我注意到Andreas Magnusson的回答与Explorer的“弹出”按钮的效果并不完全相同。具体地说,使用Andreas的代码,该驱动器在资源管理器中不会变灰,但如果使用Eject命令,则会变灰。所以我做了一些调查

我在从资源管理器(Windows7SP1 64位)运行弹出命令时运行了API监视器。我还发现了MSKB的一篇好文章(现在已经不存在了),标题是165721。文章最有趣的部分引用如下:

  • 使用GENERIC_READ | GENERIC_WRITE、FILE_SHARE_READ | FILE_SHARE_WRITE调用CreateFile,并打开现有的。lpFileName参数应为\\.\X:(其中X是实际驱动器号)。所有其他参数都可以为零
  • 通过DeviceIoControl发出FSCTL_Lock_volume IOCTL来锁定卷。如果任何其他应用程序或系统正在使用该卷,则此IOCTL将失败。一旦此函数成功返回,应用程序将保证该卷不会被系统中的任何其他对象使用
  • 通过发出FSCTL\u Dismount\u volume IOCTL卸载卷。这会导致文件系统删除卷的所有知识,并丢弃它保留的有关卷的任何内部信息
  • 通过发出IOCTL\u存储\u介质\u移除IOCTL,确保可以移除介质。在调用此IOCTL之前,请将PREVENT_MEDIA_Removing结构的PreventMediaRemoving成员设置为FALSE。这会阻止设备移除介质
  • 使用IOCTL\ U存储\ U Eject\ U媒体IOCTL弹出媒体。如果设备不允许自动弹出,则可以跳过IOCTL_STORAGE_EJECT_介质,并指示用户移除介质
  • 关闭在第一步中获得的卷句柄或发出FSCTL\u UNLOCK\u volume IOCTL。这允许其他用户使用该驱动器 过程
  • Andreas的回答、MSKB文章以及我对Explorer的API嗅探可以总结如下:

  • CreateFile
    被调用以打开卷。(所有方法)
  • DeviceIoControl
    使用调用。(所有方法)
  • DeviceIoControl
    使用调用。(仅限Andreas和MSKB方法。资源管理器出于某种原因不调用此项。此IOCTL似乎影响驱动器在资源管理器中是否变灰。我不确定资源管理器为什么不调用此项)
  • DeviceIoControl
    调用时将成员设置为
    FALSE
    (MSKB和Explorer方法。Andreas的回答中缺少此步骤)
  • DeviceIoControl
    调用(Andreas和MSKB文章)或
    IOCTL\u DISK\u EJECT\u MEDIA
    (资源管理器;请注意,此IOCTL已被淘汰,并替换为存储IOCTL。不确定资源管理器为什么仍使用旧的IOCTL)

  • 最后,我决定遵循MSKB文章中概述的程序,因为这似乎是最彻底、最完整的程序,用MSKB文章备份。

    要关闭驱动器托盘,请按说明操作,但不要将DeviceIoControl与IOCTL\u STORAGE\u EJECT\u介质一起使用,您需要使用IOCTL\u STORAGE\u LOAD\u介质调用DeviceIoControl。

    仅供参考:www.nirsoft.net被我的公司阻止,我发现这与该程序有关。阅读这些描述并不让我担心——他们似乎很担心Nircmd,因为它是一个可以做事情的实用工具。无论是在家还是在工作中,Sophos、Avast还是ESET都不会在我的任何系统上阻止nircmd。另一方面,我从来没有听说过Prevx。这在一个有多个驱动器的系统上是如何工作的?我看不到任何指定驱动器的内容。@unixman推荐的替代方案是什么?是DeviceIoControl吗?@jalf DeviceIoControl可以工作,或者你可以尝试使用windows资源管理器外壳。例如,在我的计算机中模拟点击弹出菜单的驱动程序。下面的答案是一个DeviceIoControl方法,它支持驱动字母,这很有效,但是请注意正确的拼写<代码> DeviceIoControl < /C>(没有资本<代码> O/COD>)。C++。您需要添加一些错误处理,因为对
    CreateFile
    DeviceIoControl
    的调用都可能失败。然后您需要从程序中调用函数。但是对于
    CreateFile()
    的作用域解析,这也将编译为C代码。不确定为什么范围解析是必要的,我知道这是一个古老的答案,但可能有人会评论。注意
    IOCTL\u STORAGE\u LOAD\u MEDIA
    也可以用来关闭抽屉。@Clifford:我想我是从一些代码库复制粘贴的,在那里它被认为是必要的。当我格式化代码时(令人惊讶!这不是原始代码,因为它跨越了一个类中的多个函数并进行了错误处理),我一定错过了它。有趣的是,人们花了八年时间才注意到:)。顺便说一句,现在修复了。关于
    IOCTL\u存储\u加载\u媒体的好提示
    !原来的海报是问如何关闭CD-ROM托盘,而不是弹出它。@RossRidge:这就是为什么标题是“Windows CD-ROM弹出”?尽管有标题,问题还是很清楚的。“有人知道在Windows 2000或更高版本上以编程方式关闭CD托槽的方法吗?”(我的重点)
    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;
    }