UWP下CoreWebView2.AddHostObjectToScript调用抛出状态异常问题
问题表现
UWP 项目开发中调用 CoreWebView2.AddHostObjectToScript 方法时抛出 System.Exception,异常提示:
The group or resource is not in the correct state to perform the requested operation.(组或资源未处于执行请求操作的正确状态)
环境信息
- WebView2 SDK:1.0.1245.22 最新稳定版,同时引用
Microsoft.UI.Xaml 2.8.0-prerelease.210927001 - 运行框架:UWP
- 操作系统:Windows 11 内部版本 22000
复现步骤
- 创建UWP项目
- 添加所需NuGet包:Microsoft.Web.Webview2最新稳定版、Microsoft.UI.Xaml 2.8.0-prerelease
- 在MainPage.xaml中添加WebView2组件
- 创建添加了必要特性标记的HostObject类
- 在MainPage.xaml.cs中为WebView2添加
NavigationStarting或NavigationCompleted事件处理逻辑 - 在事件处理方法中调用
myWebView.EnsureCoreWebView2Async(),确保CoreWebView2实例不为null - 在方法内尝试调用
myWebView.CoreWebView2.AddHostObjectToScript("HostObject", hostObject)时触发异常
已尝试无效方案:新建UWP Windows运行时组件项目定义HostObject类、修改HostObject类的特性标记,均抛出相同异常。
问题相关示例代码
HostObject类定义:
[AllowForWeb] [ClassInterface(ClassInterfaceType.AutoDual)] [ComVisible(true)] public class JsCallbacksUwp { public JsCallbacksUwp() { } }
触发异常的NavigationCompleted事件代码:
private async void WebView2_NavigationCompleted(WebView2 sender, CoreWebView2NavigationCompletedEventArgs args) { await sender.EnsureCoreWebView2Async(); var browserHostObject = new JSCallbacksUwp(); sender.CoreWebView2.AddHostObjectToScript("HostObject", browserHostObject); }
问题原因
UWP平台下WebView2的AddHostObjectToScript方法不允许在导航生命周期事件(NavigationStarting/NavigationCompleted等)中调用:即使提前调用EnsureCoreWebView2Async保证CoreWebView2实例不为空,此时脚本宿主注册通道仍未处于可用状态,调用就会抛出该状态异常。
另外示例代码中存在类名大小写不一致的笔误:定义的类名为JsCallbacksUwp,实例化时写为JSCallbacksUwp,也会引发额外编译或运行错误。
修复方案
将宿主对象注册逻辑从导航事件中移出,放到CoreWebView2Initialized事件中执行,在CoreWebView2实例完全初始化完成、尚未启动导航时完成宿主对象注册即可。
具体实现代码如下:
- 为WebView2控件绑定CoreWebView2Initialized事件,可在XAML中配置,也可在页面构造函数中绑定:
// 页面构造函数中绑定事件 public MainPage() { InitializeComponent(); myWebView.CoreWebView2Initialized += MyWebView_CoreWebView2Initialized; }
- 在Initialized事件处理方法中完成宿主对象注册,注册完成后再执行页面导航:
private async void MyWebView_CoreWebView2Initialized(WebView2 sender, CoreWebView2InitializedEventArgs args) { // 该事件触发时CoreWebView2已完成初始化,无需重复调用EnsureCoreWebView2Async var browserHostObject = new JsCallbacksUwp(); sender.CoreWebView2.AddHostObjectToScript("HostObject", browserHostObject); // 宿主注册完成后再导航到目标页面 sender.CoreWebView2.Navigate("https://你的目标页面地址"); }
如果需要在页面导航后动态更新注入对象,不要在导航事件中直接调用AddHostObjectToScript,可在初始化阶段先注册一个固定的调度宿主对象,后续通过该调度对象间接转发调用逻辑,避免触发状态异常。
内容的提问来源于stack exchange,提问作者Vasilios Giogourtsoglou

