webview2 打开网页时一片空白

在 WPF 中使用 webview2 组件来展示网页,若打开之后,界面显示空白,目前读者遇到的可能的原因有:

  1. webview2 环境缺失或版本不对
  2. 可能安装了某个软件,其注入 dll 到 webview2 失败

可以通过以下步骤来详细排查:

排查 webview2 问题

如果 webview2 版本太低或者与使用的 webview2 SDK 不匹配时,也会出现页面空白问题,可以通过或修复 webview2 来排除 webview2 环境影响。

通过代码进行异常排查

首先监听 webview2 事件(不用看逻辑,直接复制使用):

1
webView.CoreWebView2.ProcessFailed += WebView_ProcessFailed;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// WebView_ProcessFailed
void WebView_ProcessFailed(object sender, CoreWebView2ProcessFailedEventArgs e)
{
void ReinitIfSelectedByUser(string caption, string message)
{
this.Dispatcher.InvokeAsync(() =>
{
var selection = MessageBox.Show(message, caption, MessageBoxButton.YesNo);
if (selection == MessageBoxResult.Yes)
{
// The control cannot be re-initialized so we setup a new instance to replace it.
// Note the previous instance of the control is disposed of and removed from the
// visual tree before attaching the new one.
if (_isControlInVisualTree)
{
RemoveControlFromVisualTree(webView);
}
webView.Dispose();
webView = GetReplacementControl(false);
AttachControlToVisualTree(webView);
// Set background transparent
webView.DefaultBackgroundColor = System.Drawing.Color.Transparent;
}
});
}
void ReloadIfSelectedByUser(string caption, string message)
{
this.Dispatcher.InvokeAsync(() =>
{
var selection = MessageBox.Show(message, caption, MessageBoxButton.YesNo);
if (selection == MessageBoxResult.Yes)
{
webView.Reload();
// Set background transparent
webView.DefaultBackgroundColor = System.Drawing.Color.Transparent;
}
});
}
bool IsAppContentUri(Uri source)
{
// Sample virtual host name for the app's content.
// See CoreWebView2.SetVirtualHostNameToFolderMapping: https://learn.microsoft.com/dotnet/api/microsoft.web.webview2.core.corewebview2.setvirtualhostnametofoldermapping
return source.Host == "appassets.example";
}
if (e.ProcessFailedKind == CoreWebView2ProcessFailedKind.FrameRenderProcessExited)
{
// A frame-only renderer has exited unexpectedly. Check if reload is needed.
// In this sample we only reload if the app's content has been impacted.
foreach (CoreWebView2FrameInfo frameInfo in e.FrameInfosForFailedProcess)
{
if (IsAppContentUri(new System.Uri(frameInfo.Source)))
{
System.Threading.SynchronizationContext.Current.Post((_) =>
{
ReloadIfSelectedByUser("App content frame unresponsive",
"Browser render process for app frame exited unexpectedly. Reload page?");
}, null);
}
}
return;
}
// Show the process failure details. Apps can collect info for their logging purposes.
this.Dispatcher.InvokeAsync(() =>
{
StringBuilder messageBuilder = new StringBuilder();
messageBuilder.AppendLine($"Process kind: {e.ProcessFailedKind}");
messageBuilder.AppendLine($"Reason: {e.Reason}");
messageBuilder.AppendLine($"Exit code: {e.ExitCode}");
messageBuilder.AppendLine($"Process description: {e.ProcessDescription}");
MessageBox.Show(messageBuilder.ToString(), "Child process failed", MessageBoxButton.OK);
});
if (e.ProcessFailedKind == CoreWebView2ProcessFailedKind.BrowserProcessExited)
{
ReinitIfSelectedByUser("Browser process exited",
"Browser process exited unexpectedly. Recreate webview?");
}
else if (e.ProcessFailedKind == CoreWebView2ProcessFailedKind.RenderProcessUnresponsive)
{
ReinitIfSelectedByUser("Web page unresponsive",
"Browser render process has stopped responding. Recreate webview?");
}
else if (e.ProcessFailedKind == CoreWebView2ProcessFailedKind.RenderProcessExited)
{
ReloadIfSelectedByUser("Web page unresponsive",
"Browser render process exited unexpectedly. Reload page?");
}
}

获取到异常信息后,可以根据异常信息去排查问题。

通过 webview2 运行日志排查问题

添加环境变量:WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS = --enable-logging --v=1 --log-file=c:\temp\webview2.log 来捕获 webview2 运行详细日志

通过该详细日志来分析 webview2 报错。

1
2
3
4
5
# 添加环境变量
[Environment]::SetEnvironmentVariable('WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS', '--enable-logging --v=1 --log-file=c:\temp\webview2.log' , 'User')

# 清空环境变量
[Environment]::SetEnvironmentVariable('WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS', '--enable-logging --v=1 --log-file=c:\temp\webview2.log' , 'User')

已知报错及处理方案

错误:WebView2_Child process failed ExitCode:-1073740760

可以按以下 2 种方式来解决:

  1. 方法 1:卸载影响的软件

    通过事件查看器定位是哪个第三方 dll 注入失败,如果找到对应 dll 属于哪个程序,可以对该程序进行修复或者卸载

    在 windows 搜索栏中搜索 eventvwr(又叫事件查看器),打开后找到 【应用程序和服务日志】/【Microsoft】/【Windows】/【CodeIntegrity】/【Operational】,找到错误项进行查看。

    1
    2
    3
    # 例如出现如下错误,说明是 Ldxghijt64.dll 注入失败导致的

    Code Integrity determined that a process (\Device\HarddiskVolume5\Program Files (x86)\Microsoft\EdgeWebView\Application\114.0.1823.67\msedgewebview2.exe) attempted to load \Device\HarddiskVolume5\Windows\System32\Ldxghijt64.dll that did not meet the Microsoft signing level requirements.

    特别说明:

    Ldxghijt64.dll 是厦门天税绿盾软件的 dll。

    可以在任务管理器中通过搜索 Ld 开头的进程来定位目标位置。

  2. 方法 2:禁用 dll 注入

    可以通过添加环境变量 WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS =--disable-features=RendererCodeIntegrity 来取消第三方 dll 注入

    在 powershell(非管理员) 中运行以下命令行:

    1
    [Environment]::SetEnvironmentVariable('WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS', '--disable-features=RendererCodeIntegrity' , 'User')

    若上述操作不生效,可以通过修改注册表的方式来禁用第三方 dll 注入:

    1
    "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Edge\WebView2" /v RendererCodeIntegrityEnabled /t REG_DWORD /d 0

错误:System.Runtime.nteropServices.COMException (0x8007139F)

完整的错误如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
WebView2 creation failed with exception =
System.Runtime.nteropServices.COMException (0x8007139F): 组或资源的状
态不是执行请求操作的正确状态。(异常来自 HRESULT:Ox8007139F)

System.Runtime.lnteropServices.Marshal.ThrowExceptionForHRInternal(Int3
2 errorCode, IntPtr errorlnfo)

Microsoft.Web.WebView2.Core.CoreWebView2Environment.<CreateCoreW
ebView2ControllerAsync>d_135.MoveNext0
---引发异常的上一位置中堆栈跟踪的末尾 ---
在 System.Runtime.ExceptionServices.ExceptionDispatchlnfo.Throw()

System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebu
ggerNotification(Task task)

Microsoft.Web.WebView2.Wpf.WebView2.<>c_DisplayClass34_0.<<Ensur
eCoreWebView2Async>g_Init|0>d.MoveNext()

这种情况,一般是 webview2 COM 接口导致的错误,可以通过重装WebView2 - Microsoft Edge Developer 来解决。

如果重装不能完全解决这个问题的话,可以查看 webview2 运行的日志来分析错误。

目前,作者遇到过的问题有:

  1. DPI(分辨率)的问题

    可以在程序上右键【属性/兼容性/更改高 DPI 设置】,选中界面上的 DPI 选项,如下图所示:

    image-20230728123007643

参考

  1. WebView2_Child process failed ExitCode:-1073740760
  2. Why webview2 is displayed as a white screen, but other computers can use the same application
  3. https://github.com/MicrosoftEdge/WebView2Feedback/issues/349#issuecomment-1250870240
  4. https://support.templafy.com/hc/en-us/articles/10510746266525-How-to-repair-Webview2-Runtime
  5. ldxghijt64.dll 是个什么东西? - 知乎 (zhihu.com)
  6. https://github.com/MicrosoftEdge/WebView2Feedback/issues/3008#issuecomment-1335747853
  7. How to edit, clear, and delete environment variables in Windows - Digital Citizen
  8. COMException 0x8007139F in Microsoft.Web.WebView2.WinForms.WebView2.d__13.MoveNext ·问题 #3008 ·MicrosoftEdge/WebView2Feedback (github.com)
  9. did not meet the Microsoft signing level requirements
  10. 解决Renderer Code Integrity造成Chrome浏览器崩溃