1. 程式人生 > >WinForm程序執行JS代碼的多種方法以及使用WebBrowser與JS交互

WinForm程序執行JS代碼的多種方法以及使用WebBrowser與JS交互

bce property subset func ble ica eth 多種方法 log

原文地址: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交互