怎么关闭打开某个目录的资源管理器的窗口?

geminilz 2011-01-21 09:31:00
做了个U盘设备和一个软件
现在想通过我的软件进行类似卸载的操作,但是要获取U盘的整个权限
目前测试发现有的机器上,如果通过资源管理器打开了这个U盘,也相当于这个U盘被占用。

所以我想强制关闭所有打开U盘的资源管理器,有什么方法???

有其他思路也行
...全文
943 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
geminilz 2011-01-24
  • 打赏
  • 举报
回复
你只要强制卸载卷就可以了。最简单的办法是调用fsutil来卸载卷。
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/fsutil_volume.mspx?mfr=true
====
这个似乎不能强制卸载,并且XP下我卸载FAT分区不行,提示需要NTFS分区

还有很多种办法,比如先用CreateFile打开那个卷("\\.\X:",FILE_SHARE_READ 且 FILE_SHARE_WRITE),用DeviceIoControl先FSCTL_LOCK_VOLUME再FSCTL_DISMOUNT_VOLUME然后FSCTL_UNLOCK_VOLUME(一定要Unlock),记得要关闭打开的文件句柄。可以参考这里:
http://msdn.microsoft.com/en-us/library/aa364562(v=vs.85).aspx
=====
我目前就是用的这种方法,但是关键在于 FSCTL_LOCK_VOLUME锁定 失败,我才想关闭打开的窗口


或者调用WIM服务,用Win32_Volume类的Dismount功能(设置Force为True)。
http://msdn.microsoft.com/en-us/library/aa390368(v=vs.85).aspx
====
这个XP不支持吧

请Bokutake再帮忙看看
geminilz 2011-01-24
  • 打赏
  • 举报
回复
如果有资源管理器打开U盘,FSCTL_LOCK_VOLUME失败,错误码是5,即access denied。当然不是所有机器都这样,大部分机器都是可以锁定成功的。
这个问题通过前面查找窗口的方式还是可以处理的。

目前最头痛的是:我这个程序存在U盘上,用户点击以后,会将自身拷贝到硬盘上运行。但是我调试发现,只要是最初的父进程是在U盘上,FSCTL_LOCK_VOLUME必然失败,错误码返回的是0。
我想了几种办法切断父子进程的联系,似乎都不起作用
辰岡墨竹 2011-01-24
  • 打赏
  • 举报
回复
FSCTL_LOCK_VOLUME失败,你查过GetLastError,确定错在哪里了么?卷确实打开了么?dwShareMode对不对?
其实锁定失败也是可以卸载卷的,但是那样会导致所有打开的文件句柄无效,就像Chkdsk x: /f那样强制卸载卷,不过建议你先FlushFileBuffers(hVolume),刷新一下文件缓存。然后反复试几次(至少5次)Lock并记住间隔几十毫秒(Sleep),实在不行再直接Dismount。
弹出设备用IOCTL_STORAGE_EJECT_MEDIA。
http://msdn.microsoft.com/en-us/library/ff794483(v=winembedded.1001).aspx
这个是针对Embedded的系统的,不过应该差不多。
辰岡墨竹 2011-01-23
  • 打赏
  • 举报
回复
注意Vista/Win7下要获得相应的权限才可以做那些操作的。不过不想每次都以手动以管理员方式运行。就需要在程序里加入一个Mainfest文件,要求requestedExecutionLevel="requireAdministrator"。因为只有管理员帐户才能卸载卷。
http://msdn.microsoft.com/en-us/library/bb756929.aspx
辰岡墨竹 2011-01-23
  • 打赏
  • 举报
回复
不用管那个,就算没有资源管理器窗口,还有可能有杀毒软件什么的正在打开呢?
你只要强制卸载卷就可以了。最简单的办法是调用fsutil来卸载卷。
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/fsutil_volume.mspx?mfr=true
还有很多种办法,比如先用CreateFile打开那个卷("\\.\X:",FILE_SHARE_READ 且 FILE_SHARE_WRITE),用DeviceIoControl先FSCTL_LOCK_VOLUME再FSCTL_DISMOUNT_VOLUME然后FSCTL_UNLOCK_VOLUME(一定要Unlock),记得要关闭打开的文件句柄。可以参考这里:
http://msdn.microsoft.com/en-us/library/aa364562(v=vs.85).aspx
或者调用WIM服务,用Win32_Volume类的Dismount功能(设置Force为True)。
http://msdn.microsoft.com/en-us/library/aa390368(v=vs.85).aspx

对于2000之后的系统来说,如果一个卷被卸载了,对应的资源管理器窗口会自动关闭的。
Dreadnought 2011-01-22
  • 打赏
  • 举报
回复
FindWindow SendMessage
jacky_qiu 2011-01-22
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 geminilz 的回复:]

试过了,XP下非常好用,太感谢了

WIN7下测试确实不行,不知道有没有WIN7的方法
[/Quote]

WIN7? 我用的xp啊,测试不了win7

你可以用spy++查找win7资源管理器的地址栏窗口控件的id,在修改上面的代码,
看能否获得地址栏上的地址?
geminilz 2011-01-22
  • 打赏
  • 举报
回复
试过了,XP下非常好用,太感谢了

WIN7下测试确实不行,不知道有没有WIN7的方法

geminilz 2011-01-21
  • 打赏
  • 举报
回复
这个是卸载U盘
目前我想做的其实是卸载U盘的文件系统,是需要关闭所有的打开窗口

这个纯卸载解决不了问题吧
bai_hua_lin 2011-01-21
  • 打赏
  • 举报
回复
ftp://ftp.heise.de/pub/ct/listings/0316-208.zip

http://topic.csdn.net/t/20050621/16/4097066.html
有讨论。
jacky_qiu 2011-01-21
  • 打赏
  • 举报
回复


/****************************************************************************
获取主窗口下某个子窗口的窗口句柄
参数1:最顶层父窗口
参数2:控件ID,可使用spy++(VS2008版本) 查看
****************************************************************************/
HWND FindControlWnd(HWND ParentWnd,DWORD ControlID)
{
HWND hChild = ::GetWindow(ParentWnd, GW_CHILD);

for(; hChild!=NULL ; hChild=::GetWindow(hChild,GW_HWNDNEXT))
{
//判断是否为需要的控件
if ( GetDlgCtrlID(hChild) == ControlID )
return hChild;

HWND FindWnd=FindControlWnd(hChild,ControlID);
if (FindWnd)
return FindWnd;
}
return NULL;
}

/****************************************************************************
获取资源管理器的文件夹路径
只在Xp的下测试过
****************************************************************************/
bool GetExplorerPath(HWND hwnd,TCHAR* FilePath,UINT MaxSize)
{
bool IsOpenAddressBarWndManual=false;

HWND AddressBarWnd=FindControlWnd(hwnd,41477); //找到地址栏窗口

//如果没有找到地址栏,发送菜单消息打开它
if (!AddressBarWnd)
{
// trace("发送菜单消息打开地址栏");
::SendMessage(hwnd,WM_COMMAND,MAKEWPARAM(41477,0),NULL); //发送菜单消息打开地址栏
Sleep(200);
AddressBarWnd=FindControlWnd(hwnd,41477); //找地址栏窗口
if (AddressBarWnd)
IsOpenAddressBarWndManual=true;
else
return false;
}

// trace("find AddressBarWnd");
::SendMessage(AddressBarWnd,WM_GETTEXT,(WPARAM)MaxSize,(LPARAM)FilePath);
// trace(FilePath);

//如果地址栏是我们打开的,重新关闭它
if (IsOpenAddressBarWndManual)
::SendMessage(hwnd,WM_COMMAND,MAKEWPARAM(41477,0),NULL);

return true;
}


/****************************************************************************
枚举桌面可见窗口
****************************************************************************/
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam)
{
if ( GetParent(hwnd)==NULL && IsWindowVisible(hwnd) )
{
TCHAR ClassName[100];
::GetClassName(hwnd,ClassName,sizeof(ClassName)/sizeof(TCHAR));
if (_tcscmp(_T("CabinetWClass"),ClassName)==0
|| _tcscmp(_T("ExploreWClass"),ClassName)==0 ) //是资源管理器窗口
{
TCHAR FilePath[MAX_PATH]={0};
if ( GetExplorerPath(hwnd,FilePath,sizeof(FilePath)/sizeof(TCHAR)) )
{
if (_tcsstr(FilePath,(TCHAR*)lParam)) //路径里包含有u盘的盘符
{
::PostMessage(hwnd,WM_CLOSE,NULL,NULL);
}
}
}
}
return true;
}

void CDemoDlg::OnButton1()
{
EnumWindows(EnumWindowsProc ,(LPARAM)"E:\\"); //注意U盘符大小写
}

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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