【发布时间】:2012-09-18 08:03:49
【问题描述】:
我尝试使用DeviceIoControl函数(Win32 API函数)弹出我的CDROM驱动器,当我的CDROM驱动器没有磁盘时它可以正常工作,但是插入磁盘后,Marshal.GetLastWin32Error()返回32(ERROR_SHARING_VIOLATION : 进程无法访问该文件,因为它正在被另一个进程使用),DeviceIoControl 中传递的 driveHandle 是由CreateFile() 函数创建的。
你能帮帮我吗?我喜欢这种操作光驱相关内容的方式,我可以使用 winmm.dll 来弹出我的光驱,但我认为这种方式值得一试。
好的,代码如下:
using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
namespace DVD_ejector
{
public partial class Form1 : Form
{
const int OPENEXISTING = 3;
const int IOCTL_STORAGE_EJECT_MEDIA = 2967560;
const uint GENERICREAD = 0x80000000;
const int INVALID_HANDLE = -1;
public Form1()
{
InitializeComponent();
DriveInfo[] drs = DriveInfo.GetDrives();
List<DriveInfo> cdRoms = new List<DriveInfo>();
foreach (DriveInfo dInfo in drs)
{
if (dInfo.DriveType == DriveType.CDRom)
{
cdRoms.Add(dInfo);
}
}
comboBox1.DataSource = cdRoms;
comboBox1.DisplayMember = "Name";
if (comboBox1.Items.Count > 0) comboBox1.SelectedIndex = 0;
button1.Click += (sender, e) =>
{
Eject(@"\\.\" + ((DriveInfo)comboBox1.SelectedItem).Name[0]+":");
};
}
[DllImport("kernel32", SetLastError=true)]
static extern IntPtr CreateFile(string fileName, uint desiredAccess, uint shareMode, IntPtr attributes,uint creationDisposition, uint flagsAndAttribute, IntPtr fileTemplate);
[DllImport("kernel32")]
static extern int CloseHandle(IntPtr fileHandle);
[DllImport("kernel32")]
static extern bool DeviceIoControl(IntPtr driveHandle, int ctrlCode, IntPtr inBuffer, int inBufferSize, IntPtr outBuffer, int outBufferSize, ref int bytesReturned, IntPtr overlapped);
int bytesReturned;
private void Eject(string cdDrive)
{
IntPtr driveHandle = CreateFile(cdDrive, GENERICREAD, 0, IntPtr.Zero, OPENEXISTING, 0, IntPtr.Zero);
try
{
if((int)driveHandle != INVALID_HANDLE)
DeviceIoControl(driveHandle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, ref bytesReturned, IntPtr.Zero);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
CloseHandle(driveHandle);
}
}
}
}
【问题讨论】:
-
正如它所说,有些东西正在使用它。尝试关闭它打开的任何东西(防病毒和资源管理器是不错的候选者),然后重试。
-
如果是这样,为什么其他喷射器应用程序(使用winmm.dll)可以正常工作?实际上,错误发生在调用 CreateFile 之后。我从这个论坛 StackOverFlow 的帖子中引用了弹出 CD ROM 驱动器的代码。谢谢
-
请提供用于弹出光驱的代码,没有它很难分析。
-
该代码似乎没有检查
DeviceIoControl(返回值)是否失败。 -
@Deanna:为什么你认为代码应该检查 DeviceIoControl 的失败?那只是弹出CDROM驱动器的代码,当然要检查错误,我必须在我怀疑发生错误的行之后插入像MessageBox.Show(Marshal.GetLastWin32Error().ToString()) 这样的命令。 (上面的代码只显示了错误代码,我必须在一些微软的网站上查找该错误代码)。谢谢!