移除/弹出U盘咋就这么难?

还不够格啊 2006-06-16 10:15:43
参考了以前的帖子,基本有两种方法:

1.CreateFile,DeviceIoControl,CloseHandle
2.SetupDiGetClassDevs,SetupDiEnumDeviceInfo,CM_Get_DevNode_Status,CM_Request_Device_Eject

我用了2种U盘试验: 一种是普通的U盘,一种是手机模拟的U盘

方法1对两种U盘均无效,方法2对普通U盘有效,但对手机U盘无效.
但系统的移除硬件设备操作对两种U盘均有效。

还有别的什么方法吗?操作系统怎么做的?编程如何做到?

...全文
3000 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
little_phs 2006-11-10
  • 打赏
  • 举报
回复
在头文件加上
#include <winioctl.h>
#include <string.h>
#include <ctype.h>
#include <memory.h>
就可以了
lisnower 2006-11-02
  • 打赏
  • 举报
回复
为何我在获得DBT_DEVICEARRIVAL消息后,在case DBT_DEVICEARRIVAL: 事件里调用函数CM_Request_Device_Eject时速度那么慢呢。

zhoujiamurong 2006-09-18
  • 打赏
  • 举报
回复
好东西
lisypro 2006-08-21
  • 打赏
  • 举报
回复
UP
krfstudio 2006-08-18
  • 打赏
  • 举报
回复
CreateFile,DeviceIoControl,CloseHandle 无效?代码写错了吧?
wangk 2006-08-18
  • 打赏
  • 举报
回复
http://www.codeproject.com/useritems/RemoveDriveByLetter.asp

to HuoYun0927() :
#define FILE_DEVICE_FILE_SYSTEM 0x00000009
#define METHOD_BUFFERED 0
#define FILE_ANY_ACCESS 0
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
HuoYun0927 2006-08-17
  • 打赏
  • 举报
回复
我有一个问题是:FSCTL_DISMOUNT_VOLUME 的值是多少啊!上面的程序我怎么就编译不成啊!
错误提示如下:error C2065: 'FSCTL_DISMOUNT_VOLUME' : undeclared identifier
andyzhu9 2006-07-28
  • 打赏
  • 举报
回复
study
jun_01 2006-07-28
  • 打赏
  • 举报
回复
强人好多!
linamu 2006-07-28
  • 打赏
  • 举报
回复
学习
eofhelloworld 2006-07-13
  • 打赏
  • 举报
回复
CM_Request_Device_Eject 98下怎么做
eofhelloworld 2006-07-12
  • 打赏
  • 举报
回复
CM_Request_Device_Eject 98下怎么做
张文平_ 2006-06-28
  • 打赏
  • 举报
回复
也正为此发愁
smallbirdapple 2006-06-27
  • 打赏
  • 举报
回复
关注
DrSmart 2006-06-23
  • 打赏
  • 举报
回复
楼上的判断u和光盘
u盘是DRIVE_REMOVABLE
光盘是DRIVE_CD-ROM
怎么不好判断了,

其实搂主意思是如何拔出,当然你的那种扫描方法显然不划算,当u盘插入后会有一个消息的
sealdh 2006-06-23
  • 打赏
  • 举报
回复
其实有更简单的实现方法,可以直接监视硬盘状况,
比如,原来是c:/d:/e:三个盘,

你可以每隔一段时间,重新扫描一下盘符,如果出现新的盘符,就证明有U盘插入了。当然,你先要分析是不是光盘。这个很好做。
goingup 2006-06-23
  • 打赏
  • 举报
回复
用命令行控制Windows的设备

首先呢,你要从微软网站上下载一个叫Devcon的工具:http://download.microsoft.com/download/1/1/f/11f7dd10-272d-4cd2-896f-9ce67f3e0240/devcon.exe 把它解出来(哪来的鸡蛋,我闪!)
如果你对它的实现感兴趣的话,你可以在DDK中找到它的源码:DDK root\Src\Setup\Devcon。如果只是用用它方便的话不妨接着看它的使用。
我们看看它都有些什么参数:

devcon.exe [-r] [-m:\\<machine>] <command> [<arg>]
-r if specified will reboot machine after command is complete, if needed.
<machine> 目标机器名字.
<command> 命令(见下面).
<arg>传给命令的参数.
For help on a specific command, type: devcon.exe help <command>
classfilter 允许修改class filters.
classes 显示设备安装classes.
disable 用指定的硬件名称或者instance ID禁用设备
driverfiles 列出设备安装的驱动文件.
drivernodes 显示设备的所有节点的驱动.
enable 用指定的硬件名称或者instance ID启用设备.
find 用指定的硬件名称或者instance ID查找设备.
findall 查找所有硬件设备包括不显示的.
help 显示帮助信息.
hwids 显示设备硬件ID.
install 手动安装设备.
listclass 显示所有设备的安装 class.
reboot 重启本地机器.
remove 用指定的硬件名称或者instance ID删除设备.
rescan 从新扫描硬件信息.
resources 显示设备使用的硬件资源.
restart 用指定的硬件名称或者instance ID重启设备.
stack 列出设备的驱动堆栈.
status 列出设备的状态.
update 手动更新设备驱动.
UpdateNI 不显示用户界面的更新设备状态
SetHwID 添加、删除、编辑硬件ID的顺序.
现在看看例子:
devcon -m:\\test find pci\*

如果你开启了test机器上的IPC$的话,就可以列出test上所有知道的PCI设备

devcon -r install %WINDIR%\Inf\Netloop.inf *MSLOOP

安装一个新的Microsoft loopback adaptor实例,如果要重启的话,该命令会自动重启

devcon classes

显示所有知道的安装类。包括未认识的设备如: "USB" 和描述名字如:"Universal Serial Bus controllers".

devcon classfilter upper !filter1 !filter2

删除两个指定的classfilter .

devcon classfilter lower !badfilter +goodfilter

用"goodfilter"替换"badfilter".

devcon driverfiles =ports

列出被ports安装类使用的设备驱动文件

devcon disable *MSLOOP

禁用所有硬件ID结尾有"MSLOOP"的设备

devcon drivernodes @ROOT\PCI_HAL\PNP0A03

列出所有 ROOT\PCI_HAL\PNP0A03的兼容驱动.

devcon enable '*MSLOOP

启用所有硬件ID有"*MSLOOP". 用'修饰的*不再是通配符,而是普通字符

devcon find *

列出所有设备实例.

devcon find pci\*

列出所有本地的PCI设备

devcon find =ports *pnp*

列出 ports 中包含"PNP"的硬件设备.

devcon find =ports @root\*

列出所有在顶层的 ports .

devcon listclass usb 1394

显示安装类是 USB 和 1394的设备.

devcon remove @usb\*

删除所有USB设备

devcon rescan

重新扫描即插即用设备.

devcon resources =ports

列出ports 使用的资源.

devcon restart =net @'ROOT\*MSLOOP\0000

重启 loopback adaptor ROOT\*MSLOOP\0000.

devcon hwids=mouse

显示所有鼠标设备.

devcon sethwid @ROOT\LEGACY_BEEP\0000 := beep

关联设备 beep和the legacy beep device.

devcon status @pci\*

列出所有PCI设备的状态.

Lists the status of all COM ports.

devcon update mydev.inf *pnp0501

强制更新硬件ID有pnp0501 的设备使用Mydev.inf 驱动.
执行该命令后可能返回结果1 级错误,除非你指定了 -r, 让机器自动重启.
错误等级:
0:表示成功
1:表示需要重启
2:表示失败
3:语法错误
  • 打赏
  • 举报
回复
学习!
会思考的草 2006-06-20
  • 打赏
  • 举报
回复
再转贴一个别人的解决方案:
感谢大家.问题已经解决了,不过没有用到太底层的访问USB接口的函数,仅仅使用DeviceIoControl就可以了.我把我的在MFC框架下的大致做法在这里列出,与朋友们共勉.其中有不当支出请大家批评指正.
HANDLE hDevice; // handle to the drive to be examined
BOOL bResult; // results flag
DWORD junk; // discard results
DWORD dwError;
// Open the volume
hDevice = CreateFile("\\\\.\\I:", // drive to open
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // don't copy any file's attributes

if (hDevice == INVALID_HANDLE_VALUE) // can't open the drive
{
dwError = GetLastError();
AfxMessageBox("Fail to create file!");
return ;
}

//Dismount the volume
bResult = DeviceIoControl(
hDevice, // handle to volume
FSCTL_DISMOUNT_VOLUME, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
NULL, // lpOutBuffer
0, // nOutBufferSize
&junk, // discard count of bytes returned
(LPOVERLAPPED) NULL); // synchronous I/O
if (!bResult) // IOCTL failed
{
dwError = GetLastError();
AfxMessageBox("Fail to dismount the volume!");
}

// Close the volume handle
bRet = CloseHandle(hDevice);
if (!bRet)
{
dwError = GetLastError();
AfxMessageBox("Fail to close handle!");
}

CreateFile所用I盘符是我测试时用的,要获取用户当前插入的U盘的盘符可以采用如下方法:
1)添加WM_DEVICECHANGE的消息处理函数OnDeviceChange,在该函数中捕获DBT_DEVICEARRIVAL事件(当U盘插入时,OS会发WM_DEVICECHANGE广播消息,该消息的wParam中会包含DBT_DEVICEARRIVAL事件),同时得到DEV_BROADCAST_VOLUME结构的数据,DEV_BROADCAST_VOLUME结构的dbcv_unitmask成员是一个Mask变量,最低位对应A,其次是B,...,根据它可就可以得到当前U盘的盘符了.
BOOL CMainFrame::OnDeviceChange( UINT nEventType, DWORD dwData)
{
PDEV_BROADCAST_HDR pDevBroadcastHdr;
PDEV_BROADCAST_VOLUME pDevBroadcastVolume;
CString strVolume="";
switch (nEventType)
{
case DBT_DEVICEARRIVAL:
pDevBroadcastHdr = (PDEV_BROADCAST_HDR) dwData;
if (pDevBroadcastHdr->dbch_devicetype == DBT_DEVTYP_VOLUME)
{
pDevBroadcastVolume = (PDEV_BROADCAST_VOLUME)pDevBroadcastHdr;
xJudgeDeviceChangePath(pDevBroadcastVolume->dbcv_unitmask,strVolume);
}
break;
......
default:
return TRUE;
}
.......
}

xJudgeDeviceChangePath的代码如下:
void xJudgeDeviceChangePath(DWORD dwData, CString &strPath)

{

char i;

for (i = 0; i < 26; ++i)

{

if (dwData & 0x1)

{

CString str = char(i+'A');

strPath = str+_T(":");

break;

}

dwData = dwData >> 1;

if(dwData == 0x0000) break;

}

}
会思考的草 2006-06-20
  • 打赏
  • 举报
回复
直接ShellExecute RUNDLL32.EXE shell32.dll,Control_RunDLL hotplug.dll可以弹出那个拔除优盘的对话框。
加载更多回复(5)

2,640

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧