You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebView2运行时无法读取WinRT组件问题咨询[已废弃]

重要提示:此问题相关信息已废弃,仅作历史参考。尽管问题在回答发布时已解决,但所讨论的开发范式已不再受支持或用于原定用途。

WebView2容器无法读取WinRT组件字段导致功能失效

我正在开发一款用于游戏发布的WebView2容器应用,目前遇到阻碍开发的问题——WinRT组件无法被正确读取,导致功能完全失效。例如:Javascript端需读取一个字段,用于容器应用未完全激活时(如Xbox主机打开指南菜单)阻止游戏输入,但该字段在JS端显示为undefined,导致用户输入始终被阻塞。读取用户Xbox账号游戏存档等其他功能也存在同样问题,说明WebView2读取WinRT组件存在严重问题。

字段定义

public static bool GameBarActive { get { return gameBarActive; } }

窗口激活事件处理

private static void Window_Activated(CoreWindow sender, WindowActivatedEventArgs args)
{
    if (args.WindowActivationState == CoreWindowActivationState.Deactivated)
    {
        gameBarActive = true;
    }
    else
    {
        gameBarActive = false;
    }
}

预期逻辑与JS端问题

预期逻辑:当gameBarActive为false时,公开只读的GameBarActive字段返回WinRT组件内部可写版本的值。连接WinRT组件与WebView2容器的C#代码,将其置于名为Xbox的顶级Javascript命名空间下的API类中向游戏暴露,但JS端无法识别该组件,导致检测逻辑等效于始终为true(实际无定义)。

RPG Maker MV输入检测示例

if (Xbox.API.GameBarActive == false) {
    var lastState = this._gamepadStates[gamepad.index] || [];
    var newState = [];
    var buttons = gamepad.buttons;
    var axes = gamepad.axes;
    var threshold = 0.5;
    newState[12] = false;
    newState[13] = false;
    newState[14] = false;
    newState[15] = false;
    for (var i = 0; i < buttons.length; i++) {
        newState[i] = buttons[i].pressed;
    }
    if (axes[1] < -threshold) {
        newState[12] = true;    // up
    } else if (axes[1] > threshold) {
        newState[13] = true;    // down
    }
    if (axes[0] < -threshold) {
        newState[14] = true;    // left
    } else if (axes[0] > threshold) {
        newState[15] = true;    // right
    }
    for (var j = 0; j < newState.length; j++) {
        if (newState[j] !== lastState[j]) {
            var buttonName = this.gamepadMapper[j];
            if (buttonName) {
                this._currentState[buttonName] = newState[j];
            }
        }
    }
    this._gamepadStates[gamepad.index] = newState;
}

问题分析与解决方向

问题根源分析

  1. WinRT组件暴露规则不满足:WebView2对暴露给JS的WinRT类型有严格要求,静态属性直接暴露通常不被支持——WebView2优先支持实例对象的成员,而非静态类成员。
  2. 线程上下文不匹配:Window_Activated运行在UI线程,WebView2的JS交互可能处于不同线程,静态变量的跨线程访问可能导致值未同步,甚至JS端无法获取。
  3. 命名空间与暴露方式错误:若未正确配置WebView2的AddHostObjectToScript方法,或命名空间层级未正确映射,JS端会无法找到Xbox.API对象。
  4. WinRT类型可见性问题:用于暴露的类或属性未标记[AllowForWeb]特性,导致WebView2脚本引擎无法识别该成员。

可行解决尝试方向

  • 改用实例对象暴露,替换静态类
    将GameBarActive改为非静态属性,创建API类实例后通过AddHostObjectToScript暴露:

    using Microsoft.Web.WebView2.Core;
    
    [AllowForWeb]
    public class XboxAPI
    {
        public bool GameBarActive { get; private set; }
    
        public XboxAPI()
        {
            CoreWindow.GetForCurrentThread().Activated += Window_Activated;
        }
    
        private void Window_Activated(CoreWindow sender, WindowActivatedEventArgs args)
        {
            GameBarActive = args.WindowActivationState == CoreWindowActivationState.Deactivated;
        }
    }
    
    // WebView2初始化时添加:
    webView.CoreWebView2.AddHostObjectToScript("XboxAPI", new XboxAPI());
    

    JS端对应调整访问路径:

    // 同步访问需使用sync代理
    const xboxAPI = window.chrome.webview.hostObjects.sync.XboxAPI;
    if (xboxAPI.GameBarActive === false) {
        // 输入处理逻辑
    }
    
  • 添加必要的WinRT特性标记
    所有要暴露给JS的类和成员必须添加[AllowForWeb]特性(需引用Microsoft.Web.WebView2.Core命名空间),否则WebView2会屏蔽这些成员。

  • 通过CoreDispatcher同步线程上下文
    若属性更新涉及跨线程操作,需通过CoreDispatcher确保在UI线程更新,保证WebView2能同步到最新值:

    private async void Window_Activated(CoreWindow sender, WindowActivatedEventArgs args)
    {
        await sender.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            GameBarActive = args.WindowActivationState == CoreWindowActivationState.Deactivated;
        });
    }
    
  • 手动映射自定义JS命名空间
    WebView2暴露的宿主对象默认在window.chrome.webview.hostObjects下,若要使用自定义的Xbox.API命名空间,需在JS中手动映射:

    window.Xbox = {
        API: window.chrome.webview.hostObjects.sync.XboxAPI
    };
    
  • 启用WebView2调试工具排查
    在WebView2中调用webView.CoreWebView2.OpenDevToolsWindow()启用开发者工具,在控制台直接打印Xbox.API或window.chrome.webview.hostObjects,确认对象是否存在、成员是否可见,快速定位暴露或访问问题。

内容的提问来源于stack exchange,提问作者Jeffrey Davis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:58:13