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

如何通过WebBrowser将JavaScript变量gameData传递至C#应用

解决WebBrowser控件获取JavaScript全局变量返回空的问题

看起来你遇到的核心问题是WebBrowser控件调用InvokeScript获取gameData时返回空字符串,导致后续反序列化失败。我来帮你一步步排查和解决:

1. 先确认gameData的全局作用域

首先要确保页面中的gameData是全局变量,也就是挂载在window对象上。如果它是某个函数内部的局部变量,eval是访问不到的。

你可以先在页面的控制台(按F12打开)里输入gameData,看能不能正常输出JSON结构。如果控制台里也拿不到,那问题出在页面脚本上,需要把gameData暴露到全局:

// 页面里修改gameData的定义,确保是全局的
window.gameData = { "title": "someTitle", ... };
// 或者如果是函数内生成的,执行后赋值给window对象
function initGameData() {
    var data = { ... };
    window.gameData = data;
}
initGameData();

2. 改进C#中获取变量的方式

直接用eval调用变量并不是最可靠的方式,建议在页面中添加一个全局函数来返回gameData,然后在C#中调用这个函数:

页面脚本添加:

function getGameData() {
    // 先判断变量是否存在,避免报错
    return typeof gameData !== 'undefined' ? gameData : null;
}

C#代码修改:

private void GetGameData()
{
    try
    {
        // 调用自定义函数获取对象
        var gameDataObj = webBrowser1.Document.InvokeScript("getGameData");
        if (gameDataObj != null)
        {
            // 将对象直接序列化为JSON字符串(用Newtonsoft.Json)
            json2 = Newtonsoft.Json.JsonConvert.SerializeObject(gameDataObj);
        }
        else
        {
            // 备选方案:用eval序列化后返回
            var evalResult = webBrowser1.Document.InvokeScript("eval", 
                new object[] { "typeof gameData !== 'undefined' ? JSON.stringify(gameData) : ''" });
            json2 = Convert.ToString(evalResult);
        }

        Console.WriteLine(json2);
        if (!string.IsNullOrEmpty(json2))
        {
            CheckCB();
        }
        else
        {
            MessageBox.Show("未获取到有效的gameData数据", "数据为空", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"获取数据出错:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

3. 修正DocumentCompleted的执行时机

DocumentCompleted事件可能会触发多次(比如页面加载图片、iframe时),你需要确保只在主页面完全加载时执行逻辑,同时处理页面已经加载完成后点击按钮的情况:

private bool started = false;

private void btnTransfer_Click(object sender, EventArgs e)
{
    started = true;
    // 如果页面已经加载完成,直接执行获取逻辑
    if (webBrowser1.ReadyState == WebBrowserReadyState.Complete)
    {
        GetGameData();
    }
}

private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    // 仅当主页面加载完成且started为true时执行
    if (started && e.Url.Equals(webBrowser1.Url))
    {
        GetGameData();
        started = false; // 重置状态
    }
}

4. 确认浏览器模拟设置是否正确

你提到设置了FEATURE_BROWSER_EMULATION,但要注意:

  • 如果你的程序是32位的,需要修改HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION路径下的注册表项
  • 注册表值的名称是你的可执行文件全名(比如YourApp.exe),值设为十进制的11000(对应IE11)
  • 修改注册表后必须重启你的程序才能生效

5. 替换dynamic为强类型,避免RuntimeBinderException

用dynamic反序列化很容易出现未捕获的异常,建议创建一个和gameData结构匹配的强类型类:

public class GameData
{
    [JsonProperty("title")] // 如果JSON键是小写的title,用这个特性映射
    public string Title { get; set; }
    // 根据你的JSON结构添加其他属性
}

然后修改CheckCB方法:

private void CheckCB()
{
    GameData json;
    try
    {
        json = JsonConvert.DeserializeObject<GameData>(json2);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"解析JSON出错:{ex.Message}", "解析错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    if (json == null || string.IsNullOrEmpty(json.Title))
    {
        MessageBox.Show("未获取到有效的标题数据", "数据错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        return;
    }

    // 处理标题
    string title = json.Title.Replace("/", "").Replace("\\", "").Replace("*", "").Replace(":", "")
                             .Replace("?", "").Replace("<", "").Replace(">", "").Replace("|", "")
                             .Replace(" ", "").Replace("\"", "");
    // 后续逻辑...
}

调试小技巧

如果还是有问题,可以在页面里添加console.log(gameData),然后用WebBrowser的调试工具(按F12,确保浏览器模拟设置正确)查看控制台输出,确认gameData是否正确生成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:20:14