WebView2 control works while debugging a WPF project, but not after installed via vdproj installer

0

Solution below, thanks to Poul Bak and GrooverFromHolland for pointing out my poor async implementation which helped a bit. I simply moved the source assignment into the same method after the await so order of operations is correct, and also had to first await CoreWebView2Environment.CreateAsync. Not entirely sure why this was necessary from the installed location.

private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            InitWebviewAsync();
        }

private async void InitWebviewAsync()
        {
            var userDataFolder = Setting.ExeShortcutPath + "iGo360UtilitySettingWPF.exe.WebView2";
            var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);

            if (webView != null)
            {
                await webView.EnsureCoreWebView2Async(env);
                string url = AuthHelper._loginUrl;
                webView.Source = new Uri(url);
            }
        }

Original Issue Posting below:

I currently have a WPF project working perfectly with a WebView2 control while debugging the app with Visual Studio 2019 (16.6.1) with Target .NET Framework 4.6.1.

The following are also installed:

  1. Microsoft Edge WebView2 Runtime (90.0.818.42)
  2. Microsoft Edge (90.0.818.42)

Where I run into a problem is when I install this project via a vdproj and run the application. Note, that this is on the same PC as the debugging environment which seems even more strange.

While writing this issue, I identified the cause to the error I mention further down. Resolving those errors, I copied the following from my debug folder:

  1. runtimes\win-x86\native\WebView2Loader.dll (This resolved the DLLNotFoundException)
  2. iGo360UtilitySettingWPF.exe.WebView2 (This resolved a new error, edge could not write to directory)
  3. What would be the best way to include and manage these 2 directories in a vdproj so not having to manually copy or add them in a hacky way to my project?

Now my current error is on the await line inz InitAsync:

System.Runtime.InteropServices.COMException: 'This operation returned because the timeout period expired. (Exception from HRESULT: 0x800705B4)'

The errors I originally had, but resolved above: As the WebView2 control tries to load, the app crashes. Here's the construct and init methods where it crashes on the await line in InitAsync:

public Login()
{
    string url = AuthHelper._loginUrl;

    InitializeComponent();

    InitAsync();

    if (webView != null)
    {
        webView.Source = new Uri(url);
        //webView.NavigateToString(url);
    }
}

private async void InitAsync()
{
    await webView.EnsureCoreWebView2Async(null);
}

And event viewer logs the following error:

Application: MyWebView2Wpf.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.DllNotFoundException at Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateCoreWebView2EnvironmentWithOptions(System.String, System.String, Microsoft.Web.WebView2.Core.Raw.ICoreWebView2EnvironmentOptions, Microsoft.Web.WebView2.Core.Raw.ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler) at Microsoft.Web.WebView2.Core.CoreWebView2Environment+d__3.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(System.Threading.Tasks.Task) at Microsoft.Web.WebView2.Wpf.WebView2+<>c__DisplayClass25_0+<g__Init|0>d.MoveNext() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at MyWebView2Wpf.Login+d__4.MoveNext() at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.b__6_0(System.Object) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate) at System.Windows.Threading.DispatcherOperation.InvokeImpl() at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(System.Object) at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(System.Object) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean) at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) at MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext, System.Threading.ContextCallback, System.Object) at System.Windows.Threading.DispatcherOperation.Invoke() at System.Windows.Threading.Dispatcher.ProcessQueue() at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef) at MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef) at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object) at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32) at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate) at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32) at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef) at System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame) at System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame) at System.Windows.Application.RunDispatcher(System.Object) at System.Windows.Application.RunInternal(System.Windows.Window) at System.Windows.Application.Run(System.Windows.Window) at System.Windows.Application.Run() at MyWebView2Wpf.App.Main()

.net
wpf
microsoft-edge
webview2
vdproj
asked on Stack Overflow Apr 24, 2021 by Matthew • edited Apr 25, 2021 by Matthew

2 Answers

2

After InitializeComponent(); you call InitAsync. At that time it is possible that the window or WPF-page is not loaded yet. It is better to initialize it in the Loaded event:"

 private async void Login_Loaded(object sender, RoutedEventArgs e)
        {
            if (webView != null)
            {
                try
                {
                    await webView.EnsureCoreWebView2Async(null);
                    webView.Source = new Uri("https://etc");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
answered on Stack Overflow Apr 25, 2021 by GrooverFromHolland
1

await CoreWebView2Environment.CreateAsync(null, userDataFolder); was necessary before await webView.EnsureCoreWebView2Async

And ensured webView.Source was being called only after the webView.EnsureCoreWebView2Async finished executing.

Also, made sure the data folder permissions were properly set.

answered on Stack Overflow Apr 25, 2021 by Matthew

User contributions licensed under CC BY-SA 3.0