WinForm程序执行JS代码的多种方法以及使用WebBrowser与JS交互
Posted 控件開發基礎
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WinForm程序执行JS代码的多种方法以及使用WebBrowser与JS交互相关的知识,希望对你有一定的参考价值。
原文地址:http://www.cnblogs.com/feiyuhuo/p/5474790.html
方法一
使用微软官方组件Interop.MSScriptControl
1.msscript.ocx下载的地址 http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=D05FCF37-4D9F-4769-9442-0BCEEF907033
或者点击此处下载 Interop.MSScriptControl.dll
2.项目中引用 msscript.ocx 或者 Interop.MSScriptControl.dll
现在通过这个组件的一些方法来执行JS代码,并接收方法执行后的返回值,实现代码如下:
ScriptControlClass sc = new ScriptControlClass(); //申明变量 sc.UseSafeSubset = true; //允许执行不安全的代码 sc.Language = "javascript"; //表示需要解析的语言为JavaScript sc.AddCode(Properties.Resources.GetTimes); // Properties.Resources 资源文件 string str = sc.Run("time", new object[] { "time()" }).ToString(); //第一个参数为要执行的方法名,第二个参数为方法体的传入参数,特别注意的是当JS方法中没有传入参数时,这时传递的为该方法名称,不填写的话会抛异常。然后将JS方法执行后的返回结果存储在变量str中
以下代码将组件的常用属性以及方法封装成单独的类,方便调用。
using System; using MSScriptControl; using System.Text; //导入js文件,导入js 方法字符串,然后执行js方法。 通过msscript.ocx控件执行JS脚本 ,先引用 Interop.MSScriptControl.dll //官网下载: 然后 引用 xxx.ocx就行了 http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=D05FCF37-4D9F-4769-9442-0BCEEF907033 namespace csharp中执行js方法 { class script_run { /// <summary> /// 脚本类型 /// </summary> public enum ScriptLanguage { /// <summary> /// JScript脚本语言 /// </summary> JScript, /// <summary> /// VBscript脚本语言 /// </summary> VBscript, /// <summary> /// JavaScript脚本语言 /// </summary> JavaScript } /// <summary> /// 脚本运行错误代理 /// </summary> public delegate void RunErrorHandler(); /// <summary> /// 脚本运行超时代理 /// </summary> public delegate void RunTimeoutHandler(); /// <summary> /// ScriptEngine类 /// </summary> public class ScriptEngine { private ScriptControl msc; /// <summary> /// 定义脚本运行错误事件 /// </summary> public event RunErrorHandler RunError; /// <summary> /// 定义脚本运行超时事件 /// </summary> public event RunTimeoutHandler RunTimeout; /// <summary> ///构造函数 默认为 VBscript 脚本类型 /// </summary> public ScriptEngine() : this(ScriptLanguage.VBscript) { } /// <summary> /// 构造函数 /// </summary> /// <param name="language">脚本类型</param> public ScriptEngine(ScriptLanguage language) { this.msc = new ScriptControlClass(); this.msc.UseSafeSubset = true; this.msc.Language = language.ToString(); ((DScriptControlSource_Event)this.msc).Error += new DScriptControlSource_ErrorEventHandler(OnError); ((DScriptControlSource_Event)this.msc).Timeout += new DScriptControlSource_TimeoutEventHandler(OnTimeout); } /// <summary> /// 运行Eval方法 /// </summary> /// <param name="expression">表达式</param> /// <param name="codeBody">函数体</param> /// <returns>返回值object</returns> public object Eval(string expression, string codeBody) { msc.AddCode(codeBody); return msc.Eval(expression); } /// <summary> /// 运行Eval方法 /// </summary> /// <param name="language">脚本语言</param> /// <param name="expression">表达式</param> /// <param name="codeBody">函数体</param> /// <returns>返回值object</returns> public object Eval(ScriptLanguage language, string expression, string codeBody) { if (this.Language != language) this.Language = language; return Eval(expression, codeBody); } /// <summary> /// 运行Run方法 /// </summary> /// <param name="mainFunctionName">入口函数名称 例如:add</param> /// <param name="parameters">参数:例如:new object(){"",""}</param> /// <param name="codeBody">函数体 例如:fucniton add(int a,int b){return a+b;}</param> /// <returns>返回值object:获取object.Tostring()</returns> public object Run(string mainFunctionName, object[] parameters, string codeBody) { this.msc.AddCode(codeBody); return msc.Run(mainFunctionName, parameters); } /// <summary> /// 运行Run方法 /// </summary> /// <param name="language">脚本语言</param> /// <param name="mainFunctionName">入口函数名称</param> /// <param name="parameters">参数</param> /// <param name="codeBody">函数体</param> /// <returns>返回值object</returns> public object Run(ScriptLanguage language, string mainFunctionName, object[] parameters, string codeBody) { if (this.Language != language) this.Language = language; return Run(mainFunctionName, parameters, codeBody); } /// <summary> /// 放弃所有已经添加到 ScriptControl 中的 Script 代码和对象 /// </summary> public void Reset() { this.msc.Reset(); } /// <summary> /// 获取或设置脚本语言 /// </summary> public ScriptLanguage Language { get { return (ScriptLanguage)Enum.Parse(typeof(ScriptLanguage), this.msc.Language, false); } set { this.msc.Language = value.ToString(); } } /// <summary> /// 获取或设置脚本执行时间,单位为毫秒 /// </summary> public int Timeout { get { return 0; } } /// <summary> /// 设置是否显示用户界面元素 /// </summary> public bool AllowUI { get { return this.msc.AllowUI; } set { this.msc.AllowUI = value; } } /// <summary> /// 宿主应用程序是否有保密性要求 /// </summary> public bool UseSafeSubset { get { return this.msc.UseSafeSubset; } set { this.msc.UseSafeSubset = true; } } /// <summary> /// RunError事件激发 /// </summary> private void OnError() { if (RunError != null) RunError(); } /// <summary> /// OnTimeout事件激发 /// </summary> private void OnTimeout() { if (RunTimeout != null) RunTimeout(); } } } }
缺点:
1、必须要添加微软官方组件Interop.MSScriptControl
2、不支持开发x64的程序
方法二
利用反射获取组件(推荐使用)
无需引用其它dll文件,实现代码如下:
/// <summary> /// 获取JS时间戳 13位 /// </summary> /// <returns></returns> public string GetTimeByJs() { Type obj = Type.GetTypeFromProgID("ScriptControl"); if (obj == null) return null; object ScriptControl = Activator.CreateInstance(obj); obj.InvokeMember("Language", BindingFlags.SetProperty, null, ScriptControl, new object[] { "JavaScript" }); string js = "function time(a, b, msg){ var sum = a + b; return new Date().getTime() + \': \' + msg + \' = \' + sum }"; obj.InvokeMember("AddCode", BindingFlags.InvokeMethod, null, ScriptControl, new object[] { js }); return obj.InvokeMember("Eval", BindingFlags.InvokeMethod, null, ScriptControl, new object[] { "time(a, b, \'a + b\')" }).ToString(); }
注意事项:在JS方法中传递的参数如果是字符串,参数需要使用引号括起来,否则不需要。
区别:
1、方法一需要引用dll文件,方法二不需要引用dll文件;
2、方法一不支持开发x64的程序,方法二支持;
3、执行JS方法时,如果传入的参数是字符串时,在方法二中必须要使用引号括起来,否则不需要,而方法一给JS方法传参无需使用括号。
方法三
利用WebBrowser调用空间加密JS直接获取结果
根据参数自己生成html代码,然后交给WebBrowser执行。html文件的代码如下:
<!DOCTYPE html> <html> <script type="text/javascript" src="http://ui.ptlogin2.qzone.com/js/10141/login_10.js"></script> <script type="text/javascript" > var result=$.Encryption.getEncryption("bada23","","",!1); document.write(result); </script> <body> </body> </html>
忽略脚本错误,设置WebBrowser属性:
C#代码如下:
void MainFormLoad(object sender, EventArgs e) { webBrowser1.DocumentText=File.ReadAllText(@"C:\\Users\\Administrator\\Desktop\\abc.html"); }
void Button1Click(object sender, EventArgs e) { MessageBox.Show(webBrowser1.Document.Body.OuterText); }
效果如下图所示:
补充
WebBrowser与JS交互,JS调用C#方法
以下补充一下如何使用JS调用C#方法
C#代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Runtime.InteropServices; using System.Security.Permissions; namespace test { [PermissionSet(SecurityAction.Demand, Name ="FullTrust")] [ComVisible(true)]//COM+组件可见 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { webBrowser1.Document.InvokeScript("Run", new object[] { "CShareFunction" }); } private void Form1_Load(object sender, EventArgs e) { webBrowser1.ObjectForScripting = this;//具体公开的对象,这里可以公开自定义对象 webBrowser1.Navigate(Application.StartupPath + "/dom.html"); } public void ShowMsg(string msg) { MessageBox.Show(msg); } } }
html文件的JS代码:
<html> <head> </head> <body> </body> <script type="text/javascript" charset="utf-8"> function Run(str) { window.external.ShowMsg(str); } </script> </html>
注意的地方:记得给公开对象加上以下标签属性
[PermissionSet(SecurityAction.Demand, Name ="FullTrust")] [ComVisible(true)]
运行结果:
以上是关于WinForm程序执行JS代码的多种方法以及使用WebBrowser与JS交互的主要内容,如果未能解决你的问题,请参考以下文章
winform WebBrowser控件中,cs后台代码执行动态生成的js
WinForm窗体程序中使用CefSharp获取加载后的资源截取request参数拦截response数据注入jquery文件和js代码-拦截response数据
WinForm窗体程序中使用CefSharp获取加载后的资源截取request参数拦截response数据注入jquery文件和js代码-截取request参数