如何开始为我的。net应用程序设计和实现脚本接口?

时间:2021-08-19 21:20:12

How do I get started designing and implementing a script interface for my .NET application?

如何开始为我的。net应用程序设计和实现脚本接口?

There is VSTA (the .NET equivalent of VBA for COM), but as far as I understand I would have to pay a license fee for every installation of my application. It is an open source application so this will not work.

有VSTA(在。net中相当于COM的VBA),但据我所知,我必须为每次安装我的应用程序支付许可费。它是一个开放源码应用程序,因此不能工作。

There is also e.g. the embedding of interpreters (IronPython?), but I don't understand how this would allow exposing an "object model" (see below) to external (or internal) scripts.

也有类似的嵌入解释器(IronPython?),但是我不明白这是如何允许将“对象模型”(见下文)公开给外部(或内部)脚本的。

Sub-questions:

潜在的:

  • What is the scripting interface story in .NET? Is it somehow trivial to do this in .NET?
  • .NET中的脚本接口故事是什么?在。net中这样做是否微不足道?
  • E.g. can some .NET objects in my application and their contained objects be declared to be accessible from the outside at runtime?
  • 例如,我的应用程序中的.NET对象及其包含的对象是否可以在运行时从外部声明为可访问?
  • How can external scripts access my application (through the object model)?
  • 外部脚本如何访问我的应用程序(通过对象模型)?

Background:

背景:

I have once designed and implemented a fairly involved script interface for a Macintosh application for acquisition and analysis of data from a mass spectrometer (Mac OS, System 7) and later a COM interface for a Windows application.

我曾经设计并实现了一个相当复杂的脚本界面,用于Macintosh应用程序的获取和分析,从质谱仪(Mac OS,系统7)和后来的一个Windows应用程序的COM接口。

Both were designed with an "object model" and classes (that can have properties). These are overloaded words, but in a scripting interface context object model is essentially a containment hiarchy of objects of specific classes. Classes have properties, lists of contained objects and is not only data but can have verbs as well (actions/methods). E.g. in the Macintosh case the defined application object can contain an acquisition object that have properties for voltages used in the instrument and a fireLater verb - all as seen from the external script.

两者都是用“对象模型”和类(可以有属性)来设计的。这些是重载的词,但是在脚本接口上下文对象模型中,对象模型本质上是特定类的对象的包含层次结构。类有属性,包含的对象列表,不仅是数据,还可以有动词(动作/方法)。例如,在Macintosh中,定义的应用程序对象可以包含一个获取对象,该对象具有仪器中使用的电压的属性,以及一个fireLater谓词——所有这些都可以从外部脚本中看到。

Note that in both cases the classes/objects in the programming language used to implement the application had nothing to do with the scripting object model. For the Macintosh case the mechanisms used to implement the scripting interface was defined by Apple. There were also some standards defined by Apple on how to design the object model. For instance standardised names for certain common properties in classes.

注意,在这两种情况下,用于实现应用程序的编程语言中的类/对象与脚本对象模型没有任何关系。对于Macintosh来说,用于实现脚本接口的机制是由苹果定义的。此外,苹果还制定了一些关于如何设计对象模型的标准。例如,为类中的某些公共属性标准化名称。

Or like in the COM interfaces exposed in Microsoft Office applications, where the application object can be used to add to its list of documents (with the side effect of creating the GUI representation of a document).

或者类似于在Microsoft Office应用程序中公开的COM接口,其中应用程序对象可以用于添加到其文档列表(具有创建文档的GUI表示的副作用)。

External scripts can create new objects in a container and navigate through the content of the hiarchy at any given time. In the Macintosh case scripts could be written in e.g. AppleScript or Frontier.

外部脚本可以在一个容器中创建新的对象,并在任何给定的时间内导航到组织的内容。在麦金塔案例中,脚本可以写在例如AppleScript或Frontier。

On the Macintosh the implementation of a scripting interface was very complicated. Support for it in Metroworks' C++ class library (the name escapes me right now) made it much simpler.

在Macintosh上,脚本接口的实现非常复杂。在Metroworks的c++类库中对它的支持(我现在记不住这个名字)使它简单得多。

8 个解决方案

#1


10  

[EDIT: As covered at length in the comments in this, assuming you have a significant need to enable internal scripting where you are hosting snippets or functions someone gives you to customise your app, as opposed to a purely external scenario where one is providing a facaade to allow people to dig stuff out of your app on a more rigid predefined basis]

(编辑:覆盖在这个长度在评论中,假设你有一个重要的需要启用内部脚本你在哪里举办片段或功能有人给你定制你的应用程序,而不是一个纯粹的外部场景,一个是提供一个facaade允许人们挖的东西从你的应用程序在一个更严格的预定义的基础)

IronRuby and IronPython are very neat and appropriate for this (but as the other answer says, PowerShell may be appropriate if you have a more infrastructure-type thing).

IronRuby和IronPython非常整洁并且适合于此(但是正如另一个答案所言,如果您有更基础结构类型的东西,PowerShell可能是合适的)。

EDIT: Other ideas for enabling internal scripting are

编辑:启用内部脚本的其他想法是

  • using Windows Workflow Foundation (exposing activities to it and/or hosting instances of workflows)
  • 使用Windows工作流基础(向it公开活动和/或托管工作流实例)
  • using Spring.NET's Expression Language (which is terse, easy to doc and learn but surprisingly powerful)
  • 使用Spring。NET的表达语言(简洁,容易读懂,但却出奇的强大)

EDIT 2 June 2011: IronJS may also be a suitable candidate, there's a Hanselminutes that talks it thru.

2011年6月2日:IronJS也可能是一个合适的候选人,有一段时间可以通过对话来进行。

#2


13  

Take a look at PowerShell.

看看PowerShell。

It allows you to program simple Cmdlets that are scriptable. It also supports hierachical containers (by default you have the file system, the Registry, certificates store, etc.).

它允许您编写可脚本化的简单cmdlet。它还支持hierachical容器(默认情况下,您拥有文件系统、注册表、证书存储等)。

#3


7  

I would suggest you consider the Dynamic Language Runtime as a strategy for implementing a scripting interface. Details:

我建议您考虑动态语言运行时作为实现脚本接口的策略。细节:

The DLR currently supports IronPython and IronRuby, plus a number of other language implementations can be found on CodePlex. If you are interested in creating a language specific to your application Bitwise Magazine has a good primer article.

DLR目前支持IronPython和IronRuby,在CodePlex上还可以找到许多其他的语言实现。如果您对创建特定于应用程序的语言感兴趣,位元杂志有一篇很好的入门文章。

Dino Viehland's PDC09 session Using Dynamic Languages to Build Scriptable Applications is worth watching. You can find the demo code here.

Dino Viehland使用动态语言构建可脚本应用程序的PDC09会话值得关注。您可以在这里找到演示代码。

#4


6  

The Lua scripting language is free, used in a large number of commercial applications, and is easily embeddable into a .NET application using the freely-available LuaInterface library, which permits you to expose types and methods from your application that scripts in your embedded interpreter can leverage.

Lua脚本语言是免费的,在大量的商业应用程序中使用,并且可以使用免费的LuaInterface库很容易地嵌入到. net应用程序中,LuaInterface库允许您从应用程序中公开类型和方法,而嵌入解释器中的脚本可以利用这些类型和方法。

A tutorial on how to embed Lua into a C# application can be found here.

关于如何将Lua嵌入c#应用程序的教程可以在这里找到。

Edit: It's probably also worth noting that Lua was designed from the ground up to be an embedded scripting language, and as a result, the interpreter is highly customizable. The host application can restrict almost any aspect of the interpretation capabilities as part of the security model; e.g. allowing or preventing scripts from making network connections or writing to files, etc.

编辑:可能也值得注意的是Lua是从头设计成嵌入式脚本语言的,因此,解释器是高度可定制的。主机应用程序可以将解释能力的几乎任何方面限制为安全模型的一部分;允许或阻止脚本进行网络连接或写入文件等。

Also, you asked about external scripts. Making your program available to out-of-process scripts is done in the same way you make it available to out-of-process applications: by exposing a standardized automation interface through some sort of communication protocol. On Windows, for same-machine cross-process communication, that will most commonly be COM, but it could also be WCF, TCP remoting, RPC or any number of other communications standards. What you choose to do depends heavily on how your application is built and what kind of external automation you intend for it to do.

此外,您还询问了有关外部脚本的问题。使程序对进程外脚本可用的方法与对进程外应用程序可用的方法相同:通过某种通信协议公开标准化的自动化接口。在Windows上,对于同机跨进程通信,最常见的是COM,但也可以是WCF、TCP远程处理、RPC或任何其他通信标准。您选择做什么在很大程度上取决于您的应用程序是如何构建的,以及您打算让它做什么样的外部自动化。

#5


5  

I used CS-Script to create something like you want. In my case I defined an interface in my application. A script then just needed to implement this interface so that it could be run from the application. My application was about processing scanned images and therefore my interface looked something like this:

我使用CS-Script来创建你想要的东西。在我的例子中,我在我的应用程序中定义了一个接口。然后只需要一个脚本来实现这个接口,这样它就可以从应用程序中运行。我的应用程序是关于处理扫描图像的,因此我的界面看起来是这样的:

public interface ICustomModule
{
    void ProcessBatch(IBatch batch)
}

This way my script could access the object model that I defined in my application (in my case through IBatch). The good thing was that during development I could use a normal Class Library project for the script: IntelliSense, debugging... I do not remember the exact details but I basically had a switch in my application that told the app to use the referenced class library instead of a script.

这样,我的脚本就可以访问我在应用程序中定义的对象模型(在我的例子中是通过IBatch)。好在在开发过程中,我可以对脚本使用一个普通的类库项目:IntelliSense, debug……我不记得确切的细节,但我的应用程序中有一个开关,告诉应用程序使用引用的类库而不是脚本。

Furthermore I made an additional interface that allowed the scripts to be configured: A script could define a set of properties which were then displayed by my application in a property grid. I think I used this version here as this seemed a bit more flexible at the time. This way you can not only allow users to configure the script, but you can also provide help in form of descriptions, choices, default values... The property grid is quite extensible: In one case we had a script that would display a special form to define some complex settings.

此外,我还做了一个允许对脚本进行配置的附加接口:脚本可以定义一组属性,然后由应用程序在属性网格中显示这些属性。我想我在这里使用了这个版本,因为它在当时看起来比较灵活。这样,您不仅可以允许用户配置脚本,还可以提供描述、选择、默认值等形式的帮助……属性网格是相当可扩展的:在一种情况下,我们有一个脚本,它将显示一个特殊的表单来定义一些复杂的设置。

Edit: The application of course did not have a reference to "debug" class library. It just need to load the assembly...

编辑:应用程序当然没有“调试”类库的引用。它只需要加载程序集……

#6


5  

For a free, easy to implement .NET scripting language, have a look at C#.

对于一个免费的,易于实现的。net脚本语言,看看c#。

See my answer to a similar question.

看看我对类似问题的回答。

As for exposing data, seeing how it's a .NET language, you just need to add your program into the assemblies to link into and make the relevant classes public.

至于公开数据,要了解它是一种。net语言,只需将程序添加到程序集中,以链接到相关的类并使其公开。

#7


4  

I'm not sure this will cover your needs, but via reflection you can compile C# code and execute it at runtime (example code here).

我不确定这是否能满足您的需求,但是通过反射,您可以编译c#代码并在运行时执行它(这里的示例代码)。

So you could write the script in eg. C# and then compile "it on the fly" and run it directly in the context of your application. Of course you have to keep security considerations in mind, but if the scripts are trusted then it might work for you, and you get the benefits of using a powerful managed language for your scripts.

所以你可以用eg写剧本。然后“动态编译”并在应用程序的上下文中直接运行它。当然,您必须记住安全性的考虑,但是如果脚本是可信的,那么它可能对您有用,并且您可以为您的脚本使用强大的托管语言。

If you need high performance or running thousands of scripts it might be too slow though.

如果您需要高性能或运行数千个脚本,那么它可能太慢了。

#8


3  

I implemented CS-Script as the scripting platform last for a workflow system I wrote. Each wrokflow needed had different conditions that dictated what users would subscribe to various tasks and who would receive emails. With a scripting model it became easy to introduce new steps into the workflows and handle unique requirements that those tasks required.

我将CS-Script作为我编写的工作流系统的脚本平台。需要的每个wrokflow都有不同的条件,这些条件决定了用户将订阅什么任务,以及谁将接收电子邮件。使用脚本模型,很容易在工作流中引入新步骤,并处理这些任务所需的惟一需求。

The other nice by product of the scripting model was that workflows could be tested under a variety of conditions, and an iterative approach could be taken to finalize the workflow behaviors. During QA and user acceptance testing I included logging functions in the scripts to that I could hunt issues more easily.

脚本模型的另一个优点是工作流可以在各种条件下进行测试,并且可以采用迭代方法来完成工作流行为。在QA和用户接受测试期间,我在脚本中包含了日志功能,以便更容易地查找问题。

With CS-Script you have complete access to you objects; that is, when your script imports your assemblies you can instantiate your object in your script code. Furthermore, you can retain your compiled scripts and simply supply parameters to them. If your assemblies use a parameters object or a Dictionary, you can pass that your script and execute methods on the objects contained in the parameter object.

使用cs脚本,您可以完全访问您的对象;也就是说,当脚本导入程序集时,可以在脚本代码中实例化对象。此外,您可以保留已编译的脚本并只向它们提供参数。如果您的程序集使用一个参数对象或一个字典,您可以传递您的脚本并对包含在参数对象中的对象执行方法。

#1


10  

[EDIT: As covered at length in the comments in this, assuming you have a significant need to enable internal scripting where you are hosting snippets or functions someone gives you to customise your app, as opposed to a purely external scenario where one is providing a facaade to allow people to dig stuff out of your app on a more rigid predefined basis]

(编辑:覆盖在这个长度在评论中,假设你有一个重要的需要启用内部脚本你在哪里举办片段或功能有人给你定制你的应用程序,而不是一个纯粹的外部场景,一个是提供一个facaade允许人们挖的东西从你的应用程序在一个更严格的预定义的基础)

IronRuby and IronPython are very neat and appropriate for this (but as the other answer says, PowerShell may be appropriate if you have a more infrastructure-type thing).

IronRuby和IronPython非常整洁并且适合于此(但是正如另一个答案所言,如果您有更基础结构类型的东西,PowerShell可能是合适的)。

EDIT: Other ideas for enabling internal scripting are

编辑:启用内部脚本的其他想法是

  • using Windows Workflow Foundation (exposing activities to it and/or hosting instances of workflows)
  • 使用Windows工作流基础(向it公开活动和/或托管工作流实例)
  • using Spring.NET's Expression Language (which is terse, easy to doc and learn but surprisingly powerful)
  • 使用Spring。NET的表达语言(简洁,容易读懂,但却出奇的强大)

EDIT 2 June 2011: IronJS may also be a suitable candidate, there's a Hanselminutes that talks it thru.

2011年6月2日:IronJS也可能是一个合适的候选人,有一段时间可以通过对话来进行。

#2


13  

Take a look at PowerShell.

看看PowerShell。

It allows you to program simple Cmdlets that are scriptable. It also supports hierachical containers (by default you have the file system, the Registry, certificates store, etc.).

它允许您编写可脚本化的简单cmdlet。它还支持hierachical容器(默认情况下,您拥有文件系统、注册表、证书存储等)。

#3


7  

I would suggest you consider the Dynamic Language Runtime as a strategy for implementing a scripting interface. Details:

我建议您考虑动态语言运行时作为实现脚本接口的策略。细节:

The DLR currently supports IronPython and IronRuby, plus a number of other language implementations can be found on CodePlex. If you are interested in creating a language specific to your application Bitwise Magazine has a good primer article.

DLR目前支持IronPython和IronRuby,在CodePlex上还可以找到许多其他的语言实现。如果您对创建特定于应用程序的语言感兴趣,位元杂志有一篇很好的入门文章。

Dino Viehland's PDC09 session Using Dynamic Languages to Build Scriptable Applications is worth watching. You can find the demo code here.

Dino Viehland使用动态语言构建可脚本应用程序的PDC09会话值得关注。您可以在这里找到演示代码。

#4


6  

The Lua scripting language is free, used in a large number of commercial applications, and is easily embeddable into a .NET application using the freely-available LuaInterface library, which permits you to expose types and methods from your application that scripts in your embedded interpreter can leverage.

Lua脚本语言是免费的,在大量的商业应用程序中使用,并且可以使用免费的LuaInterface库很容易地嵌入到. net应用程序中,LuaInterface库允许您从应用程序中公开类型和方法,而嵌入解释器中的脚本可以利用这些类型和方法。

A tutorial on how to embed Lua into a C# application can be found here.

关于如何将Lua嵌入c#应用程序的教程可以在这里找到。

Edit: It's probably also worth noting that Lua was designed from the ground up to be an embedded scripting language, and as a result, the interpreter is highly customizable. The host application can restrict almost any aspect of the interpretation capabilities as part of the security model; e.g. allowing or preventing scripts from making network connections or writing to files, etc.

编辑:可能也值得注意的是Lua是从头设计成嵌入式脚本语言的,因此,解释器是高度可定制的。主机应用程序可以将解释能力的几乎任何方面限制为安全模型的一部分;允许或阻止脚本进行网络连接或写入文件等。

Also, you asked about external scripts. Making your program available to out-of-process scripts is done in the same way you make it available to out-of-process applications: by exposing a standardized automation interface through some sort of communication protocol. On Windows, for same-machine cross-process communication, that will most commonly be COM, but it could also be WCF, TCP remoting, RPC or any number of other communications standards. What you choose to do depends heavily on how your application is built and what kind of external automation you intend for it to do.

此外,您还询问了有关外部脚本的问题。使程序对进程外脚本可用的方法与对进程外应用程序可用的方法相同:通过某种通信协议公开标准化的自动化接口。在Windows上,对于同机跨进程通信,最常见的是COM,但也可以是WCF、TCP远程处理、RPC或任何其他通信标准。您选择做什么在很大程度上取决于您的应用程序是如何构建的,以及您打算让它做什么样的外部自动化。

#5


5  

I used CS-Script to create something like you want. In my case I defined an interface in my application. A script then just needed to implement this interface so that it could be run from the application. My application was about processing scanned images and therefore my interface looked something like this:

我使用CS-Script来创建你想要的东西。在我的例子中,我在我的应用程序中定义了一个接口。然后只需要一个脚本来实现这个接口,这样它就可以从应用程序中运行。我的应用程序是关于处理扫描图像的,因此我的界面看起来是这样的:

public interface ICustomModule
{
    void ProcessBatch(IBatch batch)
}

This way my script could access the object model that I defined in my application (in my case through IBatch). The good thing was that during development I could use a normal Class Library project for the script: IntelliSense, debugging... I do not remember the exact details but I basically had a switch in my application that told the app to use the referenced class library instead of a script.

这样,我的脚本就可以访问我在应用程序中定义的对象模型(在我的例子中是通过IBatch)。好在在开发过程中,我可以对脚本使用一个普通的类库项目:IntelliSense, debug……我不记得确切的细节,但我的应用程序中有一个开关,告诉应用程序使用引用的类库而不是脚本。

Furthermore I made an additional interface that allowed the scripts to be configured: A script could define a set of properties which were then displayed by my application in a property grid. I think I used this version here as this seemed a bit more flexible at the time. This way you can not only allow users to configure the script, but you can also provide help in form of descriptions, choices, default values... The property grid is quite extensible: In one case we had a script that would display a special form to define some complex settings.

此外,我还做了一个允许对脚本进行配置的附加接口:脚本可以定义一组属性,然后由应用程序在属性网格中显示这些属性。我想我在这里使用了这个版本,因为它在当时看起来比较灵活。这样,您不仅可以允许用户配置脚本,还可以提供描述、选择、默认值等形式的帮助……属性网格是相当可扩展的:在一种情况下,我们有一个脚本,它将显示一个特殊的表单来定义一些复杂的设置。

Edit: The application of course did not have a reference to "debug" class library. It just need to load the assembly...

编辑:应用程序当然没有“调试”类库的引用。它只需要加载程序集……

#6


5  

For a free, easy to implement .NET scripting language, have a look at C#.

对于一个免费的,易于实现的。net脚本语言,看看c#。

See my answer to a similar question.

看看我对类似问题的回答。

As for exposing data, seeing how it's a .NET language, you just need to add your program into the assemblies to link into and make the relevant classes public.

至于公开数据,要了解它是一种。net语言,只需将程序添加到程序集中,以链接到相关的类并使其公开。

#7


4  

I'm not sure this will cover your needs, but via reflection you can compile C# code and execute it at runtime (example code here).

我不确定这是否能满足您的需求,但是通过反射,您可以编译c#代码并在运行时执行它(这里的示例代码)。

So you could write the script in eg. C# and then compile "it on the fly" and run it directly in the context of your application. Of course you have to keep security considerations in mind, but if the scripts are trusted then it might work for you, and you get the benefits of using a powerful managed language for your scripts.

所以你可以用eg写剧本。然后“动态编译”并在应用程序的上下文中直接运行它。当然,您必须记住安全性的考虑,但是如果脚本是可信的,那么它可能对您有用,并且您可以为您的脚本使用强大的托管语言。

If you need high performance or running thousands of scripts it might be too slow though.

如果您需要高性能或运行数千个脚本,那么它可能太慢了。

#8


3  

I implemented CS-Script as the scripting platform last for a workflow system I wrote. Each wrokflow needed had different conditions that dictated what users would subscribe to various tasks and who would receive emails. With a scripting model it became easy to introduce new steps into the workflows and handle unique requirements that those tasks required.

我将CS-Script作为我编写的工作流系统的脚本平台。需要的每个wrokflow都有不同的条件,这些条件决定了用户将订阅什么任务,以及谁将接收电子邮件。使用脚本模型,很容易在工作流中引入新步骤,并处理这些任务所需的惟一需求。

The other nice by product of the scripting model was that workflows could be tested under a variety of conditions, and an iterative approach could be taken to finalize the workflow behaviors. During QA and user acceptance testing I included logging functions in the scripts to that I could hunt issues more easily.

脚本模型的另一个优点是工作流可以在各种条件下进行测试,并且可以采用迭代方法来完成工作流行为。在QA和用户接受测试期间,我在脚本中包含了日志功能,以便更容易地查找问题。

With CS-Script you have complete access to you objects; that is, when your script imports your assemblies you can instantiate your object in your script code. Furthermore, you can retain your compiled scripts and simply supply parameters to them. If your assemblies use a parameters object or a Dictionary, you can pass that your script and execute methods on the objects contained in the parameter object.

使用cs脚本,您可以完全访问您的对象;也就是说,当脚本导入程序集时,可以在脚本代码中实例化对象。此外,您可以保留已编译的脚本并只向它们提供参数。如果您的程序集使用一个参数对象或一个字典,您可以传递您的脚本并对包含在参数对象中的对象执行方法。