C#拖放在Windows 7上无法工作

48

我有一个使用C# WinForms的项目已经运行了一段时间。在Windows 7发布之前,我就实现了拖放功能,它完全正常运行。但是,在使用Windows 7时,它却无法工作。事件甚至都没有被触发。

AllowDrop属性被设置为true。当订阅DragEnter事件时,在Windows 7中它不会被调用(不确定Windows Vista是否也如此)。但在XP上,它可以正常工作。程序以管理员权限运行。

Windows 7和XP之间的拖放是否有任何区别?不知道这是否相关,但我正在使用x64。


我在一个新的Silverlight项目中遇到了类似的问题。拖放功能无法正常工作,因为我的浏览器安全特性。你在winforms中使用浏览器控件吗? - Tim
2
我注意到在Windows 7中以提升的权限运行应用程序时,拖放功能会被禁用。 - sshow
6个回答

80

源进程和目标进程需要具有兼容的安全级别/权限。例如,如果您的源是资源管理器(Explorer),并且它以用户级别权限运行,而您的目标应用程序以管理员(提升)级别权限运行,则您将无法执行拖放操作,因为这被视为安全问题,因为目标正在以更高的特权级别运行。


4
应该提供动力来改变需要改变的内容,以便您的应用程序可以作为标准用户运行。例如,不要写入程序文件,不要写入HKLM等位置。 - Kate Gregory
2
@Oskar Kjellin 如果你仍需要拖放功能,可以将需要提升权限的部分分离出来,作为一个单独的提升权限进程启动,这样主要部分就可以作为标准用户运行。 - Kate Gregory
奇怪的是,即使我没有请求管理员权限,这对我也没有用。 我下载了http://www.codeproject.com/KB/shell/Explorer_Drag_Drop/ExplorerDragAndDrop.zip并在常规权限下运行。 我尝试从在用户权限下运行的Windows资源管理器中拖动文件,但应用程序不允许进行拖放。 - Alex
11
很遗憾,Windows没有告诉用户它正在执行这个操作。就用户(和开发者)而言,该应用程序似乎不再支持拖放功能。我的应用程序可以以普通用户身份运行,但我将 VS 作为管理员运行,以便能够注册 COM DLLs。 - Qwertie
你如何设置你的应用程序,使其仅具有用户级别的权限?如果从Visual Studio运行调试模式下的应用程序,你该如何做到这一点? - wip
显示剩余4条评论

19

它被称为UIPI,即用户界面特权隔离。旨在防止以受限权限运行的程序的输入注入攻击。 它可以被禁用,你需要执行以下操作:

  • 修改清单,将<requestedExecutionLevel>元素的uiAccess属性设置为true。
  • 将程序的EXE存储在c:\ windows或c:\ program files的子目录中
  • 使用来自有效代码签名授权机构的证书对您的EXE进行签名

实际上从未尝试过这个,结果可能有所不同。


2
+1 很好的答案 :) 感谢你解答了如何解决它。不过对我来说不值得 :) - Oskar Kjellin

1
dmex的帖子中有一个小补充。 以下定义了变量和常量。
private const uint WM_DROPFILES = 0x233;
private const uint WM_COPYDATA = 0x004A;
private const uint WM_COPYGLOBALDATA = 0x0049;
private const uint MSGFLT_ADD = 1;

另外,如果您的应用程序在Windows 7上运行,您可能想考虑使用{{link1:ChangeWindowMessageFilterEx}}。我还相信OLE拖放可能不使用Windows消息。因此,它不会对其产生任何影响。


1
从您的应用程序中,使用以下值调用ChangeWindowMessageFilter,以允许在您的提升应用程序和非提升应用程序(如资源管理器)之间进行拖放:
ChangeWindowMessageFilter (WM_DROPFILES, MSGFLT_ADD);
ChangeWindowMessageFilter (WM_COPYDATA, MSGFLT_ADD);
ChangeWindowMessageFilter (0x0049, MSGFLT_ADD);

3
拖放功能不再使用窗口消息,ChangeWindowMessageFilter 不起作用。 - Hans Passant
1
@HansPassant,您能提供一些细节吗? - ken2k
@ken2k - 除此之外,没有什么需要说的了。D+D现在已经在COM中实现,IDropSource和IDropTarget是核心接口。 - Hans Passant

1

这可能与主题无关,但我在Windows 8上遇到了一些奇怪的拖放问题。它能够工作一段时间,然后停止工作。我不能在资源管理器、编辑器等之间进行拖放。事实证明,当我与运行Windows 7的Hyper-V虚拟机交互时,我的拖放能力会发生改变(或者可能是模拟crtl-alt-delete到Hyper-V的ctrl-alt-end按键)。总之,在出现问题后,以下解决了它:

我在这里找到了解决方案: 在Windows 7 Vista XP中修复拖放功能不起作用

基本上解决方法如下:

在资源管理器中左键单击一个文件,同时按住鼠标按钮,按下[Esc],然后按下[Ctrl],然后释放鼠标按钮。我必须认为这将重置某些辅助功能设置或其他东西。


1
我在使用VS 2015和Windows 7 x64操作系统调试桌面C#应用程序时遇到了同样的问题。这是因为在我的桌面上VS IDE的快捷方式上应用了管理员权限(请参见屏幕截图)。取消此选项后,拖放事件可以正常触发。感谢TimLloyd提供的帮助。

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接