【问题标题】:Programatically ejecting and retracting the CD drive in vb.net or c#在 vb.net 或 c# 中以编程方式弹出和收回 CD 驱动器
【发布时间】:2010-11-29 18:46:39
【问题描述】:

有什么办法吗?我知道它可以以某种方式以编程方式弹出/收回 cd 驱动器,因为 Roxio 在提示我插入磁盘时会这样做。

c# 或 vb.net 更可取,但 c 和 c++ 也可以作为最后的手段。

我几乎肯定有一些方法可以做到这一点,我只是不知道要调用的方法。

我确实理解这是一个有点不寻常的请求,因为当我搜索这些方法时,Google 完全没有结果...

【问题讨论】:

    标签: c# vb.net drive


    【解决方案1】:
    using System.Runtime.InteropServices;
    
    [DllImport("winmm.dll")]
    static extern Int32 mciSendString(String command, StringBuilder buffer, Int32 bufferSize, IntPtr hwndCallback);
    
    // To open the door
    mciSendString("set CDAudio door open", null, 0, IntPtr.Zero);
    
    // To close the door
    mciSendString("set CDAudio door closed", null, 0, IntPtr.Zero);
    

    http://www.geekpedia.com/tutorial174_Opening-and-closing-the-CD-tray-in-.NET.html

    【讨论】:

    • 有时工作。不是每次。替代解决方案对我来说更可靠。但请务必阅读评论并使用 FILE_SHARE_READ 和 FILE_SHARE_WRITE。
    【解决方案2】:

    这是已接受解决方案的替代解决方案,从 VB.NET sample 转换而来:

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    
    class Test
    {
        const int OPEN_EXISTING = 3;
        const uint GENERIC_READ = 0x80000000;
        const uint GENERIC_WRITE = 0x40000000;
        const uint IOCTL_STORAGE_EJECT_MEDIA = 2967560;
    
        [DllImport("kernel32")]
        private static extern IntPtr CreateFile
            (string filename, uint desiredAccess, 
             uint shareMode, IntPtr securityAttributes,
             int creationDisposition, int flagsAndAttributes, 
             IntPtr templateFile);
    
        [DllImport("kernel32")]
        private static extern int DeviceIoControl
            (IntPtr deviceHandle, uint ioControlCode, 
             IntPtr inBuffer, int inBufferSize,
             IntPtr outBuffer, int outBufferSize, 
             ref int bytesReturned, IntPtr overlapped);
    
        [DllImport("kernel32")]
        private static extern int CloseHandle(IntPtr handle);
    
        static void EjectMedia(char driveLetter)
        {
            string path = "\\\\.\\" + driveLetter + ":";
            IntPtr handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, 
                                       IntPtr.Zero, OPEN_EXISTING, 0,
                                       IntPtr.Zero);
            if ((long) handle == -1)
            {
                throw new IOException("Unable to open drive " + driveLetter);
            }
            int dummy = 0;
            DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, 
                            IntPtr.Zero, 0, ref dummy, IntPtr.Zero);
            CloseHandle(handle);
        }
    
        static void Main()
        {
            EjectMedia('f');
        }
    }
    

    【讨论】:

    • 这是最好的主意。它假设硬件上的东西。如果您的硬件有用于弹出的特殊驱动程序怎么办?你最好使用Shell的弹出功能,这会让你的代码更短更通用。
    • 我发现这比接受的答案更可靠。但是根据文档 (msdn.microsoft.com/en-us/library/windows/desktop/aa363216.aspx),“在调用 CreateFile 以打开设备驱动程序的句柄时,您应该指定 FILE_SHARE_READ 和 FILE_SHARE_WRITE 访问标志。”在它对我有用之前,我必须添加它。我编辑了你的答案以包括这些。
    • 我同意 FILE_SHARE_READ 和 FILE_SHARE_WRITE。如果未指定,任何其他同时尝试访问驱动器的进程都会导致 CreateFile 失败。
    • 这是一个带有共享标志的“补丁”: const uint FILE_SHARE_READ = 0x00000001;常量 uint FILE_SHARE_WRITE = 0x00000002; (...) IntPtr 句柄 = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, (...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 2012-12-20
    相关资源
    最近更新 更多