MicrosoftEdge / WebView2Feedback

Feedback and discussions about Microsoft Edge WebView2
https://aka.ms/webview2
439 stars 51 forks source link

Crash when disposing WPF inside ElementHost (Winforms hosting WPF) #1971

Open carsonwilliamsdev opened 2 years ago

carsonwilliamsdev commented 2 years ago

I have a WPF control with a WebView2 browser in it that gets displayed inside a WinForms dialog using an ElementHost. Whenever I close the WinForms dialog, WebView2 crashes.

at Microsoft.Web.WebView2.Core.CoreWebView2Controller.set_IsVisible(Boolean value)\r\n at Microsoft.Web.WebView2.Wpf.WebView2.UIElement_IsVisibleChanged(Object sender, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.UIElement.InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property)\r\n at System.Windows.UIElement.OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\r\n at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)\r\n at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)\r\n at System.Windows.UIElement.UpdateIsVisibleCache()\r\n at System.Windows.PresentationSource.RootChanged(Visual oldRoot, Visual newRoot)\r\n at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)\r\n at System.Windows.Interop.HwndSource.Dispose(Boolean disposing)\r\n at System.Windows.Interop.HwndSource.OnHwndDisposed(Object sender, EventArgs args)\r\n at MS.Win32.HwndWrapper.Dispose(Boolean disposing, Boolean isHwndBeingDestroyed)\r\n at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)\r\n at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)\r\n at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)\r\n at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)\r\n at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)\r\n at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)

Version SDK: latest Runtime: 96.0.1054.34 Framework: WPF OS: Win10 Build 19041.1348

Repro Steps Show a WPF based WebView2 browser on a form inside an ElementHost then dispose the form. I've attached a basic solution that reproduces the problem.

WinFormsEdge.zip

AB#37233343

champnic commented 2 years ago

Hey @carsonwilliamsdev - thanks for the bug report and repro app! From the call stack it looks like the WebView2 has already been disposed, and then the HWND being deleted is trying to change visibility later. I've added this bug to our backlog to take a look.

In the meantime you could try removing the WebView2 from the UI tree and disposing it separately during teardown.

Thanks!

cskwrd commented 2 years ago

Not OP. Encountering same bug.

I have never tried manipulating the logical or visual trees directly before, but in my attempts the closest I seemed to get to something working was the following exception:

System.InvalidCastException
  HResult=0x80004002
  Message=Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Controller'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{4D00C0D1-9434-4EB6-8078-8697A560334F}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
  Source=mscorlib
  StackTrace:
   at System.StubHelpers.StubHelpers.GetCOMIPFromRCW(Object objSrc, IntPtr pCPCMD, IntPtr& ppTarget, Boolean& pfNeedsRelease)
   at Microsoft.Web.WebView2.Core.Raw.ICoreWebView2Controller.get_CoreWebView2()
   at Microsoft.Web.WebView2.Core.CoreWebView2Controller.get_CoreWebView2()
   at Microsoft.Web.WebView2.Wpf.WebView2.Uninitialize(Boolean browserCrashed)
   at Microsoft.Web.WebView2.Wpf.WebView2.Dispose(Boolean disposing)
   at System.Windows.Interop.HwndHost.Finalize()

My example project (including my attempts at a work around): webview2-bug-1971.zip

cskwrd commented 2 years ago

@champnic see my results regarding your suggestion.

champnic commented 2 years ago

@carsonwilliamsdev and @cskwrd - Is there a reason you are choosing to host the WebView2 inside of an ElementHost and not using the Winforms control?

cskwrd commented 2 years ago

WebView2 is needed in a WPF UserControl already hosted in an ElementHost control.

cwensley commented 2 years ago

I am getting the same exception when using Microsoft.Web.WebView2.Wpf.WebView2 directly in a WPF app, when shown as a child of a parent window and the parent is closed.

YC commented 1 year ago

This issue seems to apply for both ElementHost and dialogs, and was suggested by a rep to be related to #246. A workaround is to manually dispose all spawned WebView2 controls before application exit. However, it would be nice if this can be addressed in WebView2.