Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception thrown when WndProc is overloaded

I'm trying to get at the Close event of the .NET WebBrowser type, which doesn't seem to work out of the box. (EDIT: This event is emitted when the window.close() call is issued in a script running in the browser.)

One solution I've seen is to extend the WebBrowser class and override the WndProc method.

My extension code is as follows:

type internal ExtendedBrowser () = class
    inherit System.Windows.Forms.WebBrowser()

    let WM_PARENTNOTIFY : int = 0x0210
    let WM_DESTROY      : int = 0x0002

    let closed : Event<unit> = new Event<unit>()

    do ()

    [<System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")>]
    override this.WndProc (msg : Message byref) =
        match msg.Msg with
        | wm when wm = WM_PARENTNOTIFY ->
            if (not base.DesignMode) && (msg.WParam.ToInt32() = WM_DESTROY)
            then closed.Trigger()
            base.DefWndProc(ref msg)
        | _ ->
            base.WndProc(ref msg)

    member this.Closed = closed.Publish
end

This ends up causing an exception to be thrown when an instance of the type is accessed:

Unhandled Exception: System.Reflection.TargetInvocationException: Unable to get the window handle for the 'ExtendedBrowser' control. Windowless ActiveX controls are not supported. ---> System.ComponentModel.Win32Exception: Error creating window handle.
   at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
   at System.Windows.Forms.Control.CreateHandle()
   at System.Windows.Forms.Control.get_Handle()
   at System.Windows.Forms.WebBrowserBase.DoVerb(Int32 verb)
   at System.Windows.Forms.WebBrowserBase.TransitionFromRunningToInPlaceActive()

   --- End of inner exception stack trace ---
   at System.Windows.Forms.WebBrowserBase.TransitionFromRunningToInPlaceActive()

   at System.Windows.Forms.WebBrowserBase.TransitionUpTo(AXState state)
   at System.Windows.Forms.WebBrowser.get_AxIWebBrowser2()
   at System.Windows.Forms.WebBrowser.PerformNavigate2(Object& URL, Object& flag
s, Object& targetFrameName, Object& postData, Object& headers)
   at System.Windows.Forms.WebBrowser.Navigate(String urlString)
   at [PRODUCT].Application.WebBrowser..ctor() in C:\[PATH]\WebBrowser.fs:line 107
   at Program.Main.main(String[] args) in C:\[PATH]\Program.fs:line 79
Press any key to continue . . .

Currently it's erroring on a call to Navigate("about:blank") (the first access of the instance after its construction). I can comment out the WndProc override and things work fine (besides missing the close event).

Someone said you had to put the security attribute on the WndProc override so I did that and it didn't fix things.

Someone else said you can disable the DEP, but I tried and it didn't let me exempt the EXE.

An instance of the extension is being created in a wrapper for the browser (also called WebBrowser) and an instance of this is being created in my main, which is runing in an [STAThread] (which also seems to be required).

Does anyone know what could be going wrong?

(What I'm really after is a way to get notification of the close event, so if someone knows an alternate route to that I'd be happy to hear it.)

like image 301
paul Avatar asked Nov 03 '22 07:11

paul


1 Answers

If you want to be notified when the WebBrowser control is closed, you might be able to create an instance of the normal WebBrowser class and add an event handler to the HandleDestroyed event -- it's fired when the form/control containing your instance of WebBrowser is closed.

If that doesn't work, you can try casting the Parent property to Form and hooking the FormClosing event; see here for an example of both techniques: HandleDestroyed event in userControl

like image 57
Jack P. Avatar answered Nov 08 '22 03:11

Jack P.