嵌入 C# 桌面应用程序的最佳脚本语言是啥? [关闭]

Posted

技术标签:

【中文标题】嵌入 C# 桌面应用程序的最佳脚本语言是啥? [关闭]【英文标题】:What is the best scripting language to embed in a C# desktop application? [closed]嵌入 C# 桌面应用程序的最佳脚本语言是什么? [关闭] 【发布时间】:2010-09-13 08:51:06 【问题描述】:

我们正在编写一个复杂的富桌面应用程序,并且需要在报告格式方面提供灵活性,因此我们认为我们只需将我们的对象模型暴露给脚本语言即可。时间是这意味着 VBA(这仍然是一个选项),但托管代码衍生 VSTA(我认为)似乎已经枯萎了。

现在在 Windows .NET 上嵌入脚本语言的最佳选择是什么?

【问题讨论】:

FWIW,我从@GrantPeter 的回答中的方法开始,使用 AppDomain 允许卸载,处理跨域对象租约续订,并摆弄沙盒安全措施。编译后的脚本可以调用主程序中的方法,返回越过 AppDomain 边界。实验可以在这里找到:github.com/fadden/DynamicScriptSandbox 【参考方案1】:

就我个人而言,我会使用 C# 作为脚本语言。 .NET 框架(以及 Mono,感谢 Matthew Scharley)实际上在框架本身中包含了每种 .NET 语言的编译器。

基本上,这个系统的实现有两个部分。

    允许用户编译代码 这相对容易,只需几行代码即可完成(尽管您可能想要添加一个错误对话框,这可能需要几十行代码,具体取决于您希望它的可用性)。

    创建和使用包含在已编译程序集中的类 这比上一步要困难一些(需要一点点反思)。基本上,您应该将已编译的程序集视为程序的“插件”。有很多教程介绍了使用 C# 创建插件系统的各种方法(Google 是您的朋友)。

我已经实现了一个“快速”应用程序来演示如何实现这个系统(包括 2 个工作脚本!)。这是应用程序的完整代码,只需新建一个并将代码粘贴到“program.cs”文件中。 在这一点上,我必须为我要粘贴的大量代码道歉(我不打算让它这么大,但我的评论有点忘乎所以)

using System; using System.Windows.Forms; using System.Reflection; using System.CodeDom.Compiler; namespace ScriptingInterface public interface IScriptType1 string RunScript(int value); namespace ScriptingExample static class Program /// /// The main entry point for the application. /// [STAThread] static void Main() // Lets compile some code (I'm lazy, so I'll just hardcode it all, i'm sure you can work out how to read from a file/text box instead Assembly compiledScript = CompileCode( "namespace SimpleScripts" + "" + " public class MyScriptMul5 : ScriptingInterface.IScriptType1" + " " + " public string RunScript(int value)" + " " + " return this.ToString() + \" just ran! Result: \" + (value*5).ToString();" + " " + " " + " public class MyScriptNegate : ScriptingInterface.IScriptType1" + " " + " public string RunScript(int value)" + " " + " return this.ToString() + \" just ran! Result: \" + (-value).ToString();" + " " + " " + ""); if (compiledScript != null) RunScript(compiledScript); static Assembly CompileCode(string code) // Create a code provider // This class implements the 'CodeDomProvider' class as its base. All of the current .Net languages (at least Microsoft ones) // come with thier own implemtation, thus you can allow the user to use the language of thier choice (though i recommend that // you don't allow the use of c++, which is too volatile for scripting use - memory leaks anyone?) Microsoft.CSharp.CSharpCodeProvider csProvider = new Microsoft.CSharp.CSharpCodeProvider(); // Setup our options CompilerParameters options = new CompilerParameters(); options.GenerateExecutable = false; // we want a Dll (or "Class Library" as its called in .Net) options.GenerateInMemory = true; // Saves us from deleting the Dll when we are done with it, though you could set this to false and save start-up time by next time by not having to re-compile // And set any others you want, there a quite a few, take some time to look through them all and decide which fit your application best! // Add any references you want the users to be able to access, be warned that giving them access to some classes can allow // harmful code to be written and executed. I recommend that you write your own Class library that is the only reference it allows // thus they can only do the things you want them to. // (though things like "System.Xml.dll" can be useful, just need to provide a way users can read a file to pass in to it) // Just to avoid bloatin this example to much, we will just add THIS program to its references, that way we don't need another // project to store the interfaces that both this class and the other uses. Just remember, this will expose ALL public classes to // the "script" options.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location); // Compile our code CompilerResults result; result = csProvider.CompileAssemblyFromSource(options, code); if (result.Errors.HasErrors) // TODO: report back to the user that the script has errored return null; if (result.Errors.HasWarnings) // TODO: tell the user about the warnings, might want to prompt them if they want to continue // runnning the "script" return result.CompiledAssembly; static void RunScript(Assembly script) // Now that we have a compiled script, lets run them foreach (Type type in script.GetExportedTypes()) foreach (Type iface in type.GetInterfaces()) if (iface == typeof(ScriptingInterface.IScriptType1)) // yay, we found a script interface, lets create it and run it! // Get the constructor for the current type // you can also specify what creation parameter types you want to pass to it, // so you could possibly pass in data it might need, or a class that it can use to query the host application ConstructorInfo constructor = type.GetConstructor(System.Type.EmptyTypes); if (constructor != null && constructor.IsPublic) // lets be friendly and only do things legitimitely by only using valid constructors // we specified that we wanted a constructor that doesn't take parameters, so don't pass parameters ScriptingInterface.IScriptType1 scriptObject = constructor.Invoke(null) as ScriptingInterface.IScriptType1; if (scriptObject != null) //Lets run our script and display its results MessageBox.Show(scriptObject.RunScript(50)); else // hmmm, for some reason it didn't create the object // this shouldn't happen, as we have been doing checks all along, but we should // inform the user something bad has happened, and possibly request them to send // you the script so you can debug this problem else // and even more friendly and explain that there was no valid constructor // found and thats why this script object wasn't run

【讨论】:

您知道这是否也适用于 Mono,还是仅适用于 .NET? 仅供参考,对于其他好奇的人,是的,这确实可以在 Mono 上编译和运行。只需要编译部分的系统引用。 这样做会污染 AppDomain @Lavinski 如果您不希望它污染您的 AppDomain,那么只需创建一个新的(无论如何这可能是个好主意,因此您可以在“脚本”上设置更严格的安全性) @Lander - 这是非常轻量级的。上面的代码是一个支持“脚本”的完整程序。 csscript.net 看起来像是对此的某种包装。这基本上是一个简单的实现。我认为一个更好的问题是“csscript.net 对我有什么作用而这没有”。我不知道 csscript 在做什么,但他们肯定知道上面的代码是做什么的,他们的库中有它(或非常相似的东西)。【参考方案2】:

IronPython。这是how to embed it的概述。

【讨论】:

【参考方案3】:

我使用CSScript 取得了惊人的效果。它确实减少了在我的可编写脚本的应用程序中进行绑定和其他低级别的工作。

【讨论】:

我在生产环境中使用 CS-Script 已经一年多了,效果非常好。 顺便说一句 - 要启用 C# 脚本支持,您可以在内部集成 C# 脚本库,或者自己进行 C# 脚本编译。我在我自己的项目中做了类似的轻量级 C# 脚本编译器:sourceforge.net/p/syncproj/code/HEAD/tree/CsScript.cs C# 脚本编译本身有点慢(例如与 .Lua 相比),如果不需要,避免额外的编译步骤是有意义的。【参考方案4】:

PowerShell 引擎旨在轻松嵌入应用程序中,使其可编写脚本。事实上,PowerShell CLI 只是引擎的一个基于文本的界面。

编辑:见https://devblogs.microsoft.com/powershell/making-applications-scriptable-via-powershell/

【讨论】:

我认为这是最好的解决方案,因为它不会将对象添加到 AppDomain。在 .Net 中,您永远无法卸载程序集或类。【参考方案5】:

Boo 语言。

【讨论】:

如果是github.com/boo-lang/boo的项目,看起来已经死了 @kristianp 截至目前,该项目每个月都有一些提交(直到一个月前)。所以也许它已经失去了一点吸引力,但它似乎还活着。【参考方案6】:

这些天我选择的脚本语言是Lua。它体积小、速度快、干净、文档齐全、支持良好,有一个很棒的community,很多大公司在industry(Adobe、暴雪、EA Games)中使用它,绝对值得一试。

要将其与 .NET 语言一起使用,LuaInterface 项目将提供您所需的一切。

【讨论】:

Lua 也用于 Garry's Mod 中的脚本,这是一款很棒的游戏 :)【参考方案7】:

为什么不试试 C#? Mono 有一个很棒的新项目,特别是用于动态评估 C#:

http://tirania.org/blog/archive/2008/Sep-10.html

【讨论】:

【参考方案8】:

如上所述的 IronRuby。作为一名 C# 程序员,我有一个有趣的项目是 C# Eval support in Mono。但它尚不可用(将成为 Mono 2.2 的一部分)。

【讨论】:

【参考方案9】:

再次为 IronPython 投票。嵌入它很简单,与 .Net 类的互操作也很简单,而且,它是 Python。

【讨论】:

【参考方案10】:

我可能会建议我目前维护的S#。它是一个开源项目,用 C# 编写,专为 .NET 应用程序设计。

最初(2007-2009)它托管在http://www.codeplex.com/scriptdotnet,但最近它被移到了github。

【讨论】:

感谢您发布您的答案!请务必仔细阅读FAQ on Self-Promotion。另请注意,每次链接到自己的网站/产品时,都要求发布免责声明。 感谢安德鲁的建议。先前的答案之一包含此脚本语言的过时链接。由于某种原因,我无法对原始答案添加评论,因此我发布了一个新答案以提供正确的链接。【参考方案11】:

试试Ela。这是一种类似于 Haskell 的函数式语言,可以 embedded 进入任何 .Net 应用程序。即使它有简单但可用的 IDE。

【讨论】:

【参考方案12】:

我还没有尝试过,但它看起来很酷:

http://www.codeplex.com/scriptdotnet

【讨论】:

【参考方案13】:

我刚刚为客户端创建了一个插件,允许他们在模块中编写 C# 代码,就像 VBA 为 Office 所做的那样。

【讨论】:

【参考方案14】:

我以前用过Lua;在 Delphi 应用程序中,但它可以嵌入到很多东西中。用于Adobe's Photoshop Lightroom。

【讨论】:

【参考方案15】:

我喜欢使用 C# 本身编写脚本。现在,在 2013 年,对 C# 脚本的支持非常好,越来越多的库可供使用。

Mono 对script C# code 有很好的支持,您只需在应用程序中包含Mono.CSharp.dll 即可将其与.NET 一起使用。对于我制作的 C# 脚本应用程序,请查看 CShell

还可以查看来自 Microsoft 的 Roslyn 中的 `ScriptEngine',但这只是 CTP。

正如一些人已经提到的,CS-Script 也已经存在了很长一段时间。

【讨论】:

以上是关于嵌入 C# 桌面应用程序的最佳脚本语言是啥? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Java:嵌入到 Java 桌面应用程序中的脚本语言(宏)

用于 Java 桌面应用程序的最佳数据库是啥 [关闭]

将 .NET Core 桌面应用程序连接到 Azure SQL Server 的最佳方式是啥

C# winform是啥

在同一条消息中从嵌入式代理接收消息的最佳方式是啥?(ActiveMQ)

c# 在 c# 应用程序中保存配置数据的最佳方法是啥。 [复制]