Winapi 我正试图使用DeviceIoControl IOCTL\u STORAGE\u eject\u介质弹出我的CD Rom驱动器,但获取错误访问冲突写入位置
我试图通过单击按钮弹出cd-Rom驱动器。当按下按钮时,CD-Rom驱动器以前正确弹出,但现在它给了我一个错误:“0xC0000005:访问冲突写入位置0x00000000”。我不确定为什么会出现此错误。我的代码如下所示,其中我的CD-Rom驱动器是D驱动器:Winapi 我正试图使用DeviceIoControl IOCTL\u STORAGE\u eject\u介质弹出我的CD Rom驱动器,但获取错误访问冲突写入位置,winapi,visual-c++,createfile,cd-rom,Winapi,Visual C++,Createfile,Cd Rom,我试图通过单击按钮弹出cd-Rom驱动器。当按下按钮时,CD-Rom驱动器以前正确弹出,但现在它给了我一个错误:“0xC0000005:访问冲突写入位置0x00000000”。我不确定为什么会出现此错误。我的代码如下所示,其中我的CD-Rom驱动器是D驱动器: #include <windows.h> #include <tchar.h> #include <stdio.h> #define BUTTON 3456 LRES
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#define BUTTON 3456
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
DWORD dwBytes;
HANDLE hCdRom;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HWND hwndButton = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"EJECT", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
180, // x position
200, // y position
100, // Button width
100, // Button height
hWnd, // Parent window
(HMENU)BUTTON, // No menu.
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL); // Pointer not needed.
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case BUTTON:
hCdRom = CreateFile(L"\\\\.\\D:",
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hCdRom == INVALID_HANDLE_VALUE)
{
wsprintf(NULL, L"Error: %d", GetLastError()); //Getting error: Exception thrown at 0x746FFA6F (user32.dll) in Project.exe: 0xC0000005: Access violation writing location 0x00000000.
return 1;
}
DeviceIoControl(hCdRom, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &dwBytes, NULL);
if (hCdRom == 0)
{
wsprintfW(NULL, L"Error: %d", GetLastError());
return 1;
}
MessageBox(NULL, L"Please insert a CD ROM in the CD tray.", L"CD ROM Drive", 0);
CloseHandle(hCdRom);
break;
}
}
}
#包括
#包括
#包括
#定义按钮3456
LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM);
双字双字节;
处理hCdRom;
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM)
{
开关(信息)
{
案例WM_创建:
{
HWND hwndButton=创建窗口(
L“BUTTON”,//预定义类;假定为Unicode
L“弹出”,//按钮文本
WS|TABSTOP | WS|u VISIBLE | WS|u CHILD | BS|u def按钮,//样式
180,//x位置
200,//y位置
100,//按钮宽度
100,//按钮高度
hWnd,//父窗口
(HMENU)按钮,//无菜单。
(HINSTANCE)GetWindowLongPtr(hWnd,GWLP_HINSTANCE),
NULL);//不需要指针。
}
case WM_命令:
{
开关(LOWORD(wParam))
{
案例按钮:
hCdRom=CreateFile(L“\\.\\D:”,
泛型|读|泛型|写,0,空,打开|存在,0,空);
if(hCdRom==无效的句柄值)
{
wsprintf(NULL,L“错误:%d”,GetLastError());//获取错误:在Project.exe中的0x746FFA6F(user32.dll)处引发异常:0xC0000005:访问冲突写入位置0x00000000。
返回1;
}
设备控制(hCdRom、IOCTL存储、弹出介质、NULL、0、NULL、0和dwBytes、NULL);
如果(hCdRom==0)
{
wsprintfW(NULL,L“错误:%d”,GetLastError());
返回1;
}
MessageBox(空,L“请在CD托盘中插入CD-ROM”,L“CD-ROM驱动器”,0);
闭合手柄(hCdRom);
打破
}
}
}
是否有人遇到此错误并知道如何修复它?因为
MessageBox
一直处于阻止状态,所以不会调用CloseHandle
。当您第二次按下按钮时,CreateFile
将再次打开CD-Rom驱动器句柄,之前的句柄尚未关闭,访问被拒绝
您只需删除此行:
MessageBox(空,L“请在CD托盘中插入CD-ROM”,L“CD-ROM驱动器”,0);
但正确的方法是添加确保处理所有消息的函数
调用默认窗口过程以为提供默认处理
应用程序未处理的任何窗口消息。此
函数可确保处理每条消息。DefWindowProc
使用窗口过程接收到的相同参数调用
这样修改,
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HWND hwndButton = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"EJECT", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
180, // x position
200, // y position
100, // Button width
100, // Button height
hWnd, // Parent window
(HMENU)BUTTON, // No menu.
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL); // Pointer not needed.
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case BUTTON:
hCdRom = CreateFile(L"\\\\.\\D:",
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hCdRom == INVALID_HANDLE_VALUE)
{
wsprintf(NULL, L"Error: %d", GetLastError()); //Getting error: Exception thrown at 0x746FFA6F (user32.dll) in Project.exe: 0xC0000005: Access violation writing location 0x00000000.
return 1;
}
DeviceIoControl(hCdRom, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &dwBytes, NULL);
if (hCdRom == 0)
{
wsprintfW(NULL, L"Error: %d", GetLastError());
return 1;
}
MessageBox(NULL, L"Please insert a CD ROM in the CD tray.", L"CD ROM Drive", 0);
CloseHandle(hCdRom);
break;
}
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
更新:
#include <tchar.h>
#include <windows.h>
#include <mmsystem.h> // for MCI functions
// Link to winmm.lib (usually included in project settings)
#pragma comment(lib, "winmm")
void ControlCdTray(TCHAR drive, DWORD command)
{
// Not used here, only for debug
MCIERROR mciError = 0;
// Flags for MCI command
DWORD mciFlags = MCI_WAIT | MCI_OPEN_SHAREABLE |
MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT;
// Open drive device and get device ID
TCHAR elementName[] = { drive };
MCI_OPEN_PARMS mciOpenParms = { 0 };
mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
mciOpenParms.lpstrElementName = elementName;
mciError = mciSendCommand(0,
MCI_OPEN, mciFlags, (DWORD_PTR)&mciOpenParms);
// Eject or close tray using device ID
MCI_SET_PARMS mciSetParms = { 0 };
mciFlags = MCI_WAIT | command; // command is sent by caller
mciError = mciSendCommand(mciOpenParms.wDeviceID,
MCI_SET, mciFlags, (DWORD_PTR)&mciSetParms);
// Close device ID
mciFlags = MCI_WAIT;
MCI_GENERIC_PARMS mciGenericParms = { 0 };
mciError = mciSendCommand(mciOpenParms.wDeviceID,
MCI_CLOSE, mciFlags, (DWORD_PTR)&mciGenericParms);
}
// Eject drive tray
void EjectCdTray(TCHAR drive)
{
ControlCdTray(drive, MCI_SET_DOOR_OPEN);
}
// Retract drive tray
void CloseCdTray(TCHAR drive)
{
ControlCdTray(drive, MCI_SET_DOOR_CLOSED);
}
int _tmain(int argc, _TCHAR* argv[])
{
EjectCdTray(TEXT('D')); // drive letter hardcoded
//CloseCdTray(TEXT('D'));
return 0;
}
#包括
#包括
#包含//用于MCI函数
//链接到winmm.lib(通常包含在项目设置中)
#pragma注释(lib,“winmm”)
无效控制CD托盘(TCHAR驱动器,DWORD命令)
{
//此处不使用,仅用于调试
MCIERROR-MCIERROR=0;
//MCI命令的标志
DWORD mciFlags=MCI_等待| MCI_开放|可共享|
MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_元素;
//打开驱动器设备并获取设备ID
TCHAR elementName[]={drive};
MCI_OPEN_PARMS mciOpenParms={0};
mciOpenParms.lpstrDeviceType=(LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
mciOpenParms.lpstrElementName=elementName;
mciError=mciSendCommand(0,
MCI_公开赛、mciFlags(DWORD_PTR)和mciOpenParms);
//使用设备ID弹出或关闭托盘
MCI_SET_PARMS mciSetParms={0};
mciFlags=MCI_WAIT | command;//该命令由调用方发送
mciError=mciSendCommand(mciOpenParms.wDeviceID,
MCI_集、mciFlags(DWORD_PTR)和mciSetParms);
//关闭设备ID
mciFlags=MCI_WAIT;
MCI_GENERIC_PARMS mciGenericParms={0};
mciError=mciSendCommand(mciOpenParms.wDeviceID,
MCI_CLOSE、mciFlags(DWORD_PTR)和mciGenericParms);
}
//弹出驱动器托盘
无效弹出CD托盘(TCHAR驱动器)
{
控制托盘(驱动器、MCI设置、门打开);
}
//收回驱动器托盘
无效关闭CD托盘(TCHAR驱动器)
{
控制托盘(驱动器、MCI设置、门关闭);
}
int _tmain(int argc,_TCHAR*argv[]
{
弹出CD托盘(文本('D');//硬编码的驱动器号
//关闭CD托盘(文本('D'));
返回0;
}
我的代码中有“default:return DefWindowProc(hWnd,message,wParam,lParam);”我没有在线包含它。我按照您的建议删除了“MessageBox(NULL,L“请在CD托盘中插入CD-ROM.”,L“CD-ROM驱动器”,0);,但它仍然没有弹出。@Alyssa还需要修改:CreateFile(L“\\\\\\\。\\D:”,
…我也有,在线键入时忘记了引号。@Alyssa第一次按下按钮时CD-ROM会弹出吗?我将函数放在开头,这对我很有效。非常感谢!