1

How can I disable dropping of files on a System.Windows.Controls.WebBrowser? From the documentation it would seem that this behaviour should be disabled by default as it is inherited from the UIElement.AllowDrop Property.

However dy default I can drag and drop files on to a WebBrowser control. Further to this it seems I can't disable this supposedly none-default behaviour. For example if I explicitly set the value of the property to false in XAML

<WebBrowser Name="webBrowser1" AllowDrop="False" />

..and/or in code-behind, i.e.

webBrowser1.AllowDrop = false;

Then I can still drag and drop files onto the control. How can I disable this behaviour and remove the security risk it creates?

Fraser
  • 12,565
  • 6
  • 46
  • 97

3 Answers3

4

Ok after hours and hours of playing with this I have come up with one solution that works. Because I am using the standard WPF webbrowser I know I can also use the "Extended Event Attributes" that Microsoft introduced for Internet Explorer.

The event I am using to disable dropping files onto the control is ondragover. Essentially I just cancel the event whenever it happens like so.

<body ondragover="window.event.returnValue=false;">

This is not really ideal - but what is good about this technique is that it allows for a whole host of other properties to be set that are not available directly from managed code. For the scrollbar state, which is not exposed in managed code, can be set this way.

<body scroll="no">
Fraser
  • 12,565
  • 6
  • 46
  • 97
2

There is a little bit tricky way to do this by Reflection:

1.) Get the underlaying browser COM instance (SHDocVw.IWebBrowser2) by invoking the getter on non public instance property "AxIWebBrowser2".

2.) Set property "RegisterAsDropTarget" to false on browser COM object also by invoking the property setter.

That's all.

var webBrowser = this.WebBrowser.GetType().InvokeMember("AxIWebBrowser2",
                                                        BindingFlags.Instance |
                                                        BindingFlags.NonPublic |
                                                        BindingFlags.GetProperty,
                                                        null,
                                                        this.WebBrowser,
                                                        new Object[] { });

webBrowser.GetType().InvokeMember("RegisterAsDropTarget",
                                  BindingFlags.Instance |
                                  BindingFlags.SetProperty,
                                  null,
                                  webBrowser,
                                  new Object[] { false });

Hint: "this.WebBrowser" is your WPF WebBrowser instance (System.Windows.Controls.WebBrowser).

VBWebProfi
  • 189
  • 2
  • 3
  • 1
    Since the AxIWebBrowser2 property is an IWebBrowser2 which is an IDispatch interface, you can simplify this a bit by declaring "dynamic webBrowser" instead of "var webBrowser" and then just accessing the second property like this: "webBrowser.RegisterAsDropTarget = false;" – cppguy Jan 14 '20 at 23:21
  • @cppguy You are right, but by starting with ``Reflection``, so followed this path to the end. Several other elements of the underlaing WebBrower control can be accessed too. But there is an hint on COM objects if you have a mass use of - don't forget to release the COM call wrapper (type ``_ComObject``) by ``Marshal.ReleaseComObject()``. For this you must understand are you user or owner of that object or handover the ownership. ``webBrowser`` is a COM object to use, created by the WebBrowser control. For object returning from ``Document`` property you will be owner of and have to destroy it. – VBWebProfi Sep 22 '20 at 22:33
  • Code can be simplified or generalized for the first step as WebBrowser control inherits from ``System.Windows.Interop.ActiveXHost`` which has a none public property ``ActiveXInstance`` for the related COM object instance. – VBWebProfi Sep 22 '20 at 22:39
1

I tried a couple of things, but it looks like the WebBrowser control asserts its primacy over and above anything the layout engine wants. It doesn't obey or even really sit in the visual tree, except for control siting. Panel.ZIndex had no effect, etc.

Perhaps a different HTML layout control would be in order, one that behaves better than the ActiveX IE 6/7/8 interface here:

Replacing .NET WebBrowser control with a better browser, like Chrome?

Community
  • 1
  • 1
Rob Perkins
  • 2,990
  • 1
  • 22
  • 49
  • I need the control to be IE as I am doing interop between managed code and a COM component in the loaded document. The COM component only works in IE. The fact that the wpf webbrowser has such a security hole in it is crazy! – Fraser Jul 16 '10 at 16:55