.Net执行JavaScript脚本,完成函数调用、变量读取设置、任意代码执行

来源:互联网 发布:java实训报告范文 编辑:程序博客网 时间:2024/06/11 20:49

这个类可以完成函数调用、变量读取设置等等与脚本代码的交互,且每个实例都是独立的互不干扰(默认的VsaEngine.CreateEngine()并非每次都创建新实例)。


using System;using System.Reflection;using System.ComponentModel;using System.Security.Permissions;using Microsoft.JScript;using Microsoft.JScript.Vsa;using Microsoft.Vsa;#pragma warning disable 618namespace NTS.JavaScript{/// <summary>/// JavaScript引擎封装类。脚本中不得重写AddReference、AddNamespace、CallDelegate,否则你会死得很难看。注意:该引擎不支持arguments,且目前尚未找到解决方案。请不要跟我提fast选项,这个我懂的。/// </summary>/// <remarks>/// <code>/// NTSJScriptRunner js=new NTSJScriptRunner();/// js.Eval("alert('中国你好!')");//对话框显示"中国你好!"/// js.Eval("AddReference('System.Windows.Forms');AddNamespace('System.Windows.Forms');");//引用所需的程序集并导入命名空间/// js.Eval("function add(a,b){MessageBox.Show(a+b);}");//定义函数add/// js.Invoke("add",1,2);//对话框显示3/// </code>/// </remarks>public class NTSJScriptRunner : Component{private System.Collections.Hashtable addedAssemblies;private System.Collections.Hashtable addedNamespaces;private VsaEngine engine;private ScriptFunction getVariable;private ScriptFunction setVariable;private ScriptFunction invoker;private ScriptFunction safeInvoker;/// <summary>/// 添加引用的程序集。在脚本中可以调用AddReference来引用新的程序集。/// </summary>/// <param name="assemblyName">程序集名。这里使用的是部分名。例如“System.IO”</param>public void AddReference(String assemblyName){if (String.IsNullOrEmpty(assemblyName) || addedAssemblies.Contains(assemblyName))return;Assembly a = Assembly.LoadWithPartialName(assemblyName);if (a == null)return;String s = a.FullName;foreach (var item in engine.Items){IVsaReferenceItem ri = item as IVsaReferenceItem;if (ri == null)continue;if (ri.AssemblyName == s){s = null;break;}}if (s == null)return;((IVsaReferenceItem)engine.Items.CreateItem(assemblyName, VsaItemType.Reference, VsaItemFlag.None)).AssemblyName = s;addedAssemblies.Add(assemblyName, null);}/// <summary>/// 导入命名空间。在脚本中可以调用AddNamespace来导入新的命名空间。/// </summary>/// <param name="namespase"></param>public void AddNamespace(String namespase){if (String.IsNullOrEmpty(namespase) || addedNamespaces.Contains(namespase))return;try{Import.JScriptImport(namespase, engine);addedNamespaces.Add(namespase, null);}catch { }}/// <summary>/// 调用委托。在脚本中可以调用CallDelegate来调用.Net委托。由于在脚本中直接调用委托时传递了脚本当前闭包作为目标实例,导致错误行为,于是才有了这个方法的存在。/// </summary>/// <param name="deligate"></param>public static void CallDelegate(Delegate deligate, params Object[] args){deligate.DynamicInvoke(args);}private delegate void CallDeligate(Delegate deligate, params Object[] args);protected override void Dispose(bool disposing){if (engine == null)return;base.Dispose(disposing);addedAssemblies.Clear();addedNamespaces.Clear();engine.Close();addedAssemblies = null;addedNamespaces = null;getVariable = null;setVariable = null;invoker = null;safeInvoker = null;engine = null;}class DefaultVsaSite : IVsaSite{// Methods[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]public virtual void GetCompiledState(out byte[] pe, out byte[] debugInfo){pe = this.Assembly;debugInfo = this.DebugInfo;}public virtual object GetEventSourceInstance(string itemName, string eventSourceName){throw new VsaException(VsaError.CallbackUnexpected);}public virtual object GetGlobalInstance(string name){throw new VsaException(VsaError.CallbackUnexpected);}[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]public virtual void Notify(string notify, object optional){throw new VsaException(VsaError.CallbackUnexpected);}// Propertiespublic virtual byte[] Assembly{get{throw new VsaException(VsaError.GetCompiledStateFailed);}}public virtual byte[] DebugInfo{get{return null;}}[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]public virtual bool OnCompilerError(IVsaError error){throw ((JScriptException)error);}}/// <summary>/// 构造封装器。/// </summary>public NTSJScriptRunner(){addedAssemblies = new System.Collections.Hashtable();addedNamespaces = new System.Collections.Hashtable();if(!DesignMode)try{engine = new VsaEngine(false);engine.InitVsaEngine("NTS.JavaScript.NTSJScriptRunner", new DefaultVsaSite());engine.SetOption("AutoRef", true);getVariable = (ScriptFunction)Eval(@"(function(name){return this[name];});");setVariable = (ScriptFunction)Eval(@"(function(name,value){this[name]=value;});");invoker = (ScriptFunction)Eval(@"(function(A7104FA513E04696,A7104FA513E04697,A7104FA513E04698){return eval(A7104FA513E04696+'('+A7104FA513E04697+')','unsafe');});");safeInvoker = (ScriptFunction)Eval(@"(function(A7104FA513E04696,A7104FA513E04697,A7104FA513E04698){return eval(A7104FA513E04696+'('+A7104FA513E04697+')');});");AddReference("System.Windows.Forms");AddNamespace("System.Windows.Forms");SetVariable("A7104FA513E04699", this);SetVariable("CallDelegate", (CallDeligate)CallDelegate);Eval("function AddReference(s){A7104FA513E04699.AddReference(s);}");Eval("function AddNamespace(s){A7104FA513E04699.AddNamespace(s);}");Eval("function alert(s){System.Windows.Forms.MessageBox.Show(s);}");}catch (Exception){}}/// <summary>/// 获取全局变量。变量不存在时返回null。/// </summary>/// <param name="name"></param>/// <returns></returns>public Object GetVariable(String name){return getVariable.Invoke(null, name);}/// <summary>/// 设置全局变量。/// </summary>/// <param name="name"></param>/// <param name="value"></param>/// <returns></returns>public Object SetVariable(String name, Object value){Object v = getVariable.Invoke(null, name);setVariable.Invoke(null, name, value);return v;}/// <summary>/// 在完全信任上下文中调用脚本中的函数。/// </summary>/// <param name="code"></param>/// <param name="parameters"></param>/// <returns></returns>public Object Invoke(String code, params Object[] parameters){if (String.IsNullOrEmpty(code))return null;String s;if (parameters == null || parameters.Length == 0)s = "";else{String[] ss = new String[parameters.Length];for (Int32 i = 0; i < parameters.Length; i++){ss[i] = "A7104FA513E04698[" + i + "]";}s = String.Join(",", ss);}return invoker.Invoke(null, code, s, parameters);}/// <summary>/// 在完全信任上下文中执行任意代码。/// </summary>/// <param name="code"></param>/// <returns></returns>public Object Eval(String code){if (String.IsNullOrEmpty(code))return null;return Microsoft.JScript.Eval.JScriptEvaluate(code, "unsafe", engine);}/// <summary>/// 在部分信任上下文中调用脚本中的函数。/// </summary>/// <param name="code"></param>/// <param name="parameters"></param>/// <returns></returns>public Object SafeInvoke(String code, params Object[] parameters){if (String.IsNullOrEmpty(code))return null;String s;if (parameters == null || parameters.Length == 0)s = "";else{String[] ss = new String[parameters.Length];for (Int32 i = 0; i < parameters.Length; i++){ss[i] = "A7104FA513E04698[" + i + "]";}s = String.Join(",", ss);}return safeInvoker.Invoke(null, code, s, parameters);}/// <summary>/// 在部分信任上下文中执行任意代码。/// </summary>/// <param name="code"></param>/// <returns></returns>public Object SafeEval(String code){if (String.IsNullOrEmpty(code))return null;return Microsoft.JScript.Eval.JScriptEvaluate(code, engine);}}}


原创粉丝点击