如何通过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
相关产品推荐
相关产品推荐

