WebView2 确保CoreWebView2Async 永远不会返回

问题描述

在我的 WPF 应用程序中,我需要显示一个 html 字符串,并且我知道我需要在调用 NavigatetoString 之前调用 ensureCoreWebView2Async 方法,否则 CoreWebView 将为空并且我会出现异常。问题是等待 ensureCoreWebView2Async 永远不会结束。

我创建了一个小应用程序来重现问题(并排除与我的大项目相关的问题),问题是一样的。

  • 如果我设置 WebView2 的 Source 属性传递一个 Url,那么它就可以工作!
  • 如果我调用 NavigatetoString 而不调用 ensureCoreWebView2Async,我会收到异常(如预期)。
  • 如果我在调用 NavigatetoString 或设置 Source 属性之前调用 ensureCoreWebView2Async(这应该不是问题,因为根据文档多次调用它应该没有任何效果),那么它会永远挂起。 调用不会引发异常,控制台中也没有消息。非常令人沮丧。

以下是示例应用程序的代码(我的主窗口有 2 个按钮,一个用于打开 url,一个用于加载 html 字符串 - 第一个有效):

<Window x:Class="WebViewApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WebViewApp" xmlns:wpf="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<StackPanel>
    <Button Width="200" Height="40" Click="OpenUrl_Click">Open url</Button>
    <Button Width="200" Height="40" Click="OpenHtml_Click">Open html</Button>
</StackPanel></Window>

MainWindow 背后的代码

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private async void OpenUrl_Click(object sender,RoutedEventArgs e)
    {
        var browserWindow = new WebWindow();
        //await browserWindow.Initialize();  // this also never completes
        browserWindow.OpenUrl("http://www.microsoft.com");
        browserWindow.Show();
    }

    private async void OpenHtml_Click(object sender,RoutedEventArgs e)
    {
        var browserWindow = new WebWindow();
        await browserWindow.Initialize();
        browserWindow.LoadHtml(@"<html><head><title>Test title</title></head><body><p>Test</p></body></html>");
        browserWindow.Show();
    }
}

这里是 browserView xaml(添加 WebView2 nuget 包):

<Window x:Class="WebViewApp.WebWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WebViewApp" xmlns:wpf="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
    mc:Ignorable="d"
    Title="WebWindow" Height="450" Width="800">
<Grid>
    <wpf:WebView2 Name="Wpfbrowser" />
</Grid></Window>

以及背后的代码

public partial class WebWindow : Window
{
    public WebWindow()
    {
        InitializeComponent();
    }

    public async Task Initialize()
    {
        try
        {
            await Wpfbrowser.EnsureCoreWebView2Async();  // never completes
        }
        catch (Exception exception)
        {
            Console.WriteLine(exception.Message);
        }
    }

    public void LoadHtml(string html)
    {
        Wpfbrowser.NavigatetoString(html);
    }

    public void OpenUrl(string url)
    {
        Wpfbrowser.source = new Uri(url);
    }
}

我也尝试过更改 Target 平台,但没有任何变化。

解决方法

您应该推迟初始化 webview 直到 OnContentRendered 被调用。我改变了你的代码,它很有魅力。请参阅下面的更改。

    public partial class WebWindow : Window
    {
        private string _url;
        private string _html;

        public WebWindow()
        {
            InitializeComponent();
        }

        protected override async void OnContentRendered(EventArgs e)
        {
            base.OnContentRendered(e);
            try
            {
                var webView2Environment = await CoreWebView2Environment.CreateAsync();
                await WpfBrowser.EnsureCoreWebView2Async(webView2Environment);

                if(!string.IsNullOrEmpty(_url))
                    WpfBrowser.Source = new Uri(_url);
                else if(!string.IsNullOrEmpty(_html))
                    WpfBrowser.NavigateToString(_html);
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message);
            }
        }

        public void ShowFromUrl(string url)
        {
            _url = url;
            Show();
        }

        public void ShowFromHtml(string html)
        {
            _html = html;
            Show();
        }
    }
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void OpenUrl_Click(object sender,RoutedEventArgs e)
        {
            var browserWindow = new WebWindow();
            browserWindow.ShowFromUrl("http://www.microsoft.com");
        }

        private async void OpenHtml_Click(object sender,RoutedEventArgs e)
        {
            var browserWindow = new WebWindow();
            browserWindow.ShowFromHtml(@"<html><head><title>Test title</title></head><body><p>Testsdfsdfsdfsdfdsfdsfklsdkflkdlf<br>dsfdsfdsfdsfsdfdsfds</p></body></html>");
        }
    }

您还可以从我的 git 存储库中查看执行类似操作的代码。 KioskBrowser (GitHub)