首页 > 编程 > JavaScript > 正文

使用C#解析并运行JavaScript代码

2019-11-17 02:28:58
字体:
来源:转载
供稿:网友

使用C#解析并运行javaScript代码

如果想在C#编程中解析并运行Javascript代码,常见的方式有两种:

  1. 利用COM组件“Microsoft Script Control”,可参见:C#使用技巧之调用JS脚本方法一
  2. 利用JScript.net,可参见:C#使用技巧之调用JS脚本方法二或从命令行编译 JScript 代码

这两种方式都能达到在C#中执行JavaScript代码的效果,不过各有利弊。 方法一对程序运行环境有要求,程序只能以x86为目标平台。方法二实际是将JavaScript代码编译成为了.NET程序集,对JavaScript代码有严格的格式要求,但是可以在任意平台发布(支持跨平台)。 除此之外,其实还有另一种方法来实现这个功能,兼容x86和x64平台,不过仅限于在Windows下使用。而且对JavaScript代码没有严格的格式要求。

Windows Script Engines

Microsoft® Windows® Script Interfaces introduce a new way for an application to add scripting and OLE Automation capabilities. With the advent of the interfaces, hosts can call upon disparate scripting engines from multiple sources and vendors to perform scripting between components. The implementation of the script itself—language, syntax, persistent format, execution model, and so on—is left to the script vendor. The designers have taken care to allow hosts that rely on Windows Script to use arbitrary language back ends.

以上是微软对Windows Script Engines的官方解释,详细信息可以参看:Microsoft Windows Script Interfaces - Introduction。简单的说,Windows Script Engines 提供了一种新的方式,让我们可以为应用程序添加脚本功能。 所以我们只需要将Windows Script Engines进行包装即可。

调用示例

1、直接执行表达式:

Console.WriteLine(ScriptEngine.Eval("jscript", "1+2/3"));

将会输出:1.66666666666667

2、调用有参数的方法:

using (ScriptEngine engine = new ScriptEngine("jscript")){  ParsedScript parsed = engine.Parse("function MyFunc(x){return 1+2+x}");  Console.WriteLine(parsed.CallMethod("MyFunc", 3));}

将会输出:6

3、调用可选参数NameItem方法:

using (ScriptEngine engine = new ScriptEngine("jscript")){    ParsedScript parsed = engine.Parse("function MyFunc(x){return 1+2+x+My.Num}");    MyItem item = new MyItem();    item.Num = 4;    engine.SetNamedItem("My", item);    Console.WriteLine(parsed.CallMethod("MyFunc", 3));}[ComVisible(true)] // Script engines are COM components.public class MyItem{    public int Num { get; set; }}

将会输出:10

如果宿主服务中安装有IE9+的浏览器,那么我们可以调用更快的JavaScript引擎"chakra":

using (ScriptEngine engine = new ScriptEngine("{16d51579-a30b-4c8b-a276-0ff4dc41e755}")){    // continue with chakra now}

ScriptEngine.cs

上面只是部分的调用示例,但是应该可以满足80%的业务需求。上面的代码依赖于ScriptEngine类,完整的ScriptEngine.cs代码如下:

/// <summary>/// RePResents a Windows Script Engine such as JScript, VBScript, etc./// </summary>public sealed class ScriptEngine : IDisposable{    /// <summary>    /// The name of the function used for simple evaluation.    /// </summary>    public const string MethodName = "EvalMethod";    /// <summary>    /// The default scripting language name.    /// </summary>    public const string DefaultLanguage = JavaScriptLanguage;    /// <summary>    /// The JavaScript or jscript scripting language name.    /// </summary>    public const string JavaScriptLanguage = "javascript";    /// <summary>    /// The javascript or jscript scripting language name.    /// </summary>    public const string VBScriptLanguage = "vbscript";    /// <summary>    /// The chakra javascript engine CLSID. The value is {16d51579-a30b-4c8b-a276-0ff4dc41e755}.    /// </summary>    public const string ChakraClsid = "{16d51579-a30b-4c8b-a276-0ff4dc41e755}";    private IActiveScript _engine;    private IActiveScriptParse32 _parse32;    private IActiveScriptParse64 _parse64;    internal ScriptSite Site;    private Version _version;    private string _name;    [Guid("BB1A2AE1-A4F9-11cf-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IActiveScript    {        [PreserveSig]        int SetScriptSite(IActiveScriptSite pass);        [PreserveSig]        int GetScriptSite(Guid riid, out IntPtr site);        [PreserveSig]        int SetScriptState(ScriptState state);        [PreserveSig]        int GetScriptState(out ScriptState scriptState);        [PreserveSig]        int Close();        [PreserveSig]        int AddNamedItem(string name, ScriptItem flags);        [PreserveSig]        int AddTypeLib(Guid typeLib, uint major, uint minor, uint flags);        [PreserveSig]        int GetScriptDispatch(string itemName, out IntPtr dispatch);        [PreserveSig]        int GetCurrentScriptThreadID(out uint thread);        [PreserveSig]        int GetScriptThreadID(uint win32ThreadId, out uint thread);        [PreserveSig]        int GetScriptThreadState(uint thread, out ScriptThreadState state);        [PreserveSig]        int InterruptScriptThread(uint thread, out System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo, uint flags);        [PreserveSig]        int Clone(out IActiveScript script);    }    [Guid("4954E0D0-FBC7-11D1-8410-006008C3FBFC"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IActiveScriptProperty    {        [PreserveSig]        int GetProperty(int dwProperty, IntPtr pvarIndex, out object pvarValue);        [PreserveSig]        int SetProperty(int dwProperty, IntPtr pvarIndex, ref object pvarValue);    }    [Guid("DB01A1E3-A42B-11cf-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IActiveScriptSite    {        [PreserveSig]        int GetLCID(out int lcid);        [PreserveSig]        int GetItemInfo(string name, ScriptInfo returnMask, out IntPtr item, IntPtr typeInfo);        [PreserveSig]        int GetDocVersionString(out string version);        [PreserveSig]        int OnScriptTerminate(object result, System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo);        [PreserveSig]        int OnStateChange(ScriptState scriptState);        [PreserveSig]        int OnScriptError(IActiveScriptError scriptError);        [PreserveSig]        int OnEnterScript();        [PreserveSig]        int OnLeaveScript();    }    [Guid("EAE1BA61-A4ED-11cf-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IActiveScriptError    {        [PreserveSig]        int GetExceptionInfo(out System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo);        [PreserveSig]        int GetSourcePosition(out uint sourceContext, out int lineNumber, out int characterPosition);        [PreserveSig]        int GetSourceLineText(out string sourceLine);    }    [Guid("BB1A2AE2-A4F9-11cf-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IActiveScriptParse32    {        [PreserveSig]        int InitNew();        [PreserveSig]        int AddScriptlet(string defaultName, string code, string itemName, string subItemName, string eventName, string delimiter, IntPtr sourceContextCookie, uint startingLineNumber, ScriptText flags, out string name, out System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo);        [PreserveSig]        int ParseScriptText(string code, string itemName, IntPtr context, string delimiter, int sourceContextCookie, uint startingLineNumber, ScriptText flags, out object result, out System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo);    }    [Guid("C7EF7658-E1EE-480E-97EA-D52CB4D76D17"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]    private interface IActiveScriptParse64    {        [PreserveSig]        int InitNew();        [PreserveSig]        int AddScriptlet(string defaultName, string code, string itemName, string subItemName, string eventName, string delimiter, IntPtr sourceContextCookie, uint startingLineNumber, ScriptText flags, out string name, out System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo);        [PreserveSig]        int ParseScriptText(string code, string itemName, IntPtr context, string delimiter, long sourceContextCookie, uint startingLineNumber, ScriptText flags, out object result, out System.Runtime.InteropServices.ComTypes.EXCEPINFO exceptionInfo);    }    [Flags]    private enum ScriptText    {        None = 0,        //DelayExecution = 1,        //IsVisible =
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表