最近工作中遇到要响应拖放文件消息,首先使用::DragAcceptFiles(m_hWnd, TRUE);来对主窗口接收拖拽事件,然后针对打开UAC的特殊情况也要处理。
我记得在前公司开发时,遇到一个升级完毕,软件打开时以管理员权限打开就无法接受文件拖拽消息。最后他们走了另一条路,使用了一个超级复杂的方法解决:重新以用户权限启动。
那还是在很早很早之前,就发现过一个奇怪的问题:Win7及以后的系统上(源于Vista),以管理员权限运行的命令提示符无法通过从资源管理器拖放文件的形式获取文件路径。
Windows的命令提示符本来就极其难用了,还tm有这种feature,真无语。
然而今天在写GUI程序时也遇到这样的问题了。
在非管理员模式下,能通过拖放拿到文件。但在管理员模式下时,拿不到,甚至连 WM_DROPFILES 消息都收不到。
通过搜索,了解到以下一些原因:
Drag and Drop File into Application under run as administrator
1 |
Your drag'n'drop isn't working for permissions levels differences, if the other program/explorer you're dragging from is not elevated as administrator Windows is smart enough to not let the user do that. |
Can’t drag and drop when ‘run as administrator’
1 2 3 4 5 6 7 8 |
The problem is tied to how security permissions work. The ability to drag and drop from a normal applications to an elevated one would break the security model behind UAC. However, I'm unclear as to why a UAC prompt isn't shown, thus allowing for a temporary elevated operation (much like any linux user experiences every day). This is definitely something that Microsoft needs to work on. What troubles me is that this problem is already old. Vista behaved the same. There's 2 things you can do (one ugly, one annoying) Ugly: Disable UAC. But you lose all the extra security it offers. Annoying: Use another File manager and run it too as an Administrator Why another file manager? Because you can't actually elevate Windows Explorer. Despite seeing the option in the context menu of the Windows Explorer icon and a UAC prompt being displayed, the fact is Windows Explorer will not be elevated. |
一言以蔽之就是:因为 UIPI 的原因,低权限的进程不能向高权限的进程发送消息。我这里就是:资源管理器向我的以管理员权限运行的程序发消息,将失败。
然而我还发现另一个问题:QQ影音在以管理员权限运行时,仍然可以支持拖放。所以我猜测估计又用了什么奇技淫巧。果然,通过文章“简单方法解决Vista/Win7 无法接收WM_DROPFILES问题”了解到,加上以下代码就可以恢复使用拖放功能的使用:
1 2 3 |
ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD); ChangeWindowMessageFilter(WM_COPYDATA, MSGFLT_ADD); ChangeWindowMessageFilter(0x49, MSGFLT_ADD);/* WM_COPYGLOBALDATA */ |
可以轻易得出一个不很确定的结论:消息其实是收到的,只是被 user32 模块给简单地过滤掉了。M$的把戏真多。