目录
介绍
概念化这个混乱
使用这个混乱
从GitHub下载最新版本
我希望在构建解析器之类时稍事休息,并做一些不同的事情,因此,我整理了一个方便的小库,用于为.NET应用程序添加脚本支持。
有时候,我发现需要在我的应用程序中执行JavaScript,有时需要抓取,有时只是为了获得JS脚本支持(VBScript也可以使用),并且至少有一次需要进行遗留ASP仿真。
Microsoft提供了COM接口来使用这些接口,但是从.NET使用它们却很丑陋。
幸运的是,这个小库使它变得容易。
概念化这个混乱Microsoft提供了可扩展的脚本框架,它们在旧版ASP页面和Internet Explorer中使用。默认情况下Windows附带的VBScript和JavaScript(JScript中),但第三方也加入了其他的内容。
这些脚本引擎是COM可见的,并将其脚本公开为COM对象,这些对象可以调用您的代码或从您的代码中调用。唯一的麻烦是接口混乱。
我所做的是将这些接口包装成两个易于使用的对象,ScriptHost和ScriptEngine。
使用这个混乱首先,脚本引擎不能自主存在。他们需要一个扎根的地方。这就是ScriptHost的作用。ScriptHost管理脚本引擎的创建和生命周期,以及为脚本引擎提供各种服务,例如错误报告和对象检索。在创建任何脚本引擎之前,我们必须创建这些小家伙之一。完成后请记住将其丢弃。关闭脚本主机也会同时关闭由它创建的所有引擎。
接下来,我们有了ScriptEngine,您可以通过ScriptHost.Create()获得它。这些代表脚本代码的自治区域。要了解这意味着什么,请知道网页中的每个块都将与其中之一相对应,并且页面本身就是ScriptHost。传递语言以Create()获取所需语言的脚本引擎。有一个“快速” JS引擎,您可以通过传递ChakraJS常量来访问它,但我尚未对其进行测试,而且我不确定它的实际速度。
使用ScriptEngine,我们可以Evaluate()表达式,Run()语句或AddCode()脚本块。我们还可以将对象添加到Globals字典中,然后可以通过脚本代码中的名称对其进行访问。
希望演示代码可以使所有内容变得清晰:
Console.WriteLine("Creating script host");
using (var host = new ScriptHost())
{
// create a JavaScript engine
Console.WriteLine("Creating javascript engine");
var engine = host.Create("javascript"); // you can use the ChakraJS const here
// for IE9+'s fast engine
// evaluate an expression
Console.WriteLine("Evaluate 2+2: ");
Console.WriteLine(engine.Evaluate("2+2"));
// add some code to the current script
Console.WriteLine("Add code: var i = 1;");
engine.AddCode("var i = 1;");
// get the object for the script
Console.Write("i = ");
dynamic obj = engine.Script;
// print var i
Console.WriteLine(obj.i);
// add an app object to the script
Console.WriteLine("Add global app object");
engine.Globals.Add("app", new AppObject());
// let the script call the app object
Console.Write("Run \"app.writeLine('Hello World!');\": ");
engine.Run("app.writeLine('Hello World!');");
}
请注意,我们已经在上面的脚本引擎中添加了AppObject。这是它的定义:
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDispatch /*.AutoDual */)] // automatically
// implements com interface IDispatch ( and IUnknown )
public class AppObject
{
///
/// allows scripts to write to the console
///
public void writeLine(string s) { Console.WriteLine(s); }
}
请注意,我们从System.Runtime.InteropServices中添加了几个属性。这是必需的,以便.NET创建使脚本通过COM/OLE Automation与对象进行通信所需的基础结构。如果不添加这些内容,则脚本将无法与对象通信,并且会出现错误。
还要注意,奇怪的是,尽管每个脚本引擎都有自己的全局变量集合,但是脚本站点内的所有全局变量共享同一个命名容器。这意味着无论使用哪个脚本引擎创建,每个名称仅支持一个全局名称。如果两个脚本引擎的项目名称相同,则只有第一个实例与该名称关联。可以将一个对象添加到具有相同名称的两个或多个脚本引擎中。我不是这样设计的——这是Microsoft Active Script框架设计的一部分。
这些涵盖了它。从这里开始并向您的应用程序添加JavaScript和VBScript脚本应该足够简单。