为您的 .NET 应用程序添加 JavaScript 和 VBScript






4.84/5 (6投票s)
使用 Microsoft 的活动脚本技术轻松为您的应用程序添加脚本支持
引言
我想暂时摆脱构建解析器之类的事情,做一些不同的事情,所以这里有一个方便的小库,我已将其添加到您的 .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()` 获取它。 这些代表脚本代码的独立区域。 为了了解这意味着什么,要知道网页中的每个 `<script>` 块都对应于其中一个,而页面本身将是 `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
{
/// <summary>
/// allows scripts to write to the console
/// </summary>
public void writeLine(string s) { Console.WriteLine(s); }
}
请注意,我们已从 `System.Runtime.InteropServices` 添加了几个属性。 这是必需的,以便 .NET 创建让脚本通过 COM/OLE 自动化与对象通信所需的基础设施。 如果您不添加这些,您的脚本将无法与您的对象通信,并且您将收到错误。
另请注意,奇怪的是,尽管每个脚本引擎都有自己的全局集合,但脚本站点中的所有全局变量都共享相同的命名容器。 这意味着无论在哪个脚本引擎下创建,每个名称只有一个全局变量是有效的。 如果两个脚本引擎具有相同名称的项,则只有第一个实例将与该名称关联。 将对象添加到两个或多个脚本引擎下相同的名称是可以的。 我不是这样设计的 - 这是 Microsoft Active Script 框架设计的一部分。
就这样。 从这里开始,将 JavaScript 和 VBScript 脚本添加到您的应用程序应该足够简单了。 玩得开心!
历史
- 2020 年 1 月 14 日 - 初次提交