複雑でリッチなデスクトップアプリケーションを作成していて、レポート形式に柔軟性を提供する必要があるため、オブジェクトモデルをスクリプト言語に公開するだけだと考えました。それはVBA(これはまだオプションです)を意味する時期でしたが、マネージコードの派生VSTA(私は思う)は衰退しているようです。
Windows .NETの組み込みスクリプト言語に最適な選択肢は何ですか?
複雑でリッチなデスクトップアプリケーションを作成していて、レポート形式に柔軟性を提供する必要があるため、オブジェクトモデルをスクリプト言語に公開するだけだと考えました。それはVBA(これはまだオプションです)を意味する時期でしたが、マネージコードの派生VSTA(私は思う)は衰退しているようです。
Windows .NETの組み込みスクリプト言語に最適な選択肢は何ですか?
回答:
私はCSScriptを使用して素晴らしい結果を得ました。スクリプト可能なアプリでバインディングやその他の低レベルのことを行う必要が本当に減りました。
個人的には、スクリプト言語としてC#を使用します。.NETフレームワーク(およびMonoのおかげで、Matthew Scharley氏)は、実際には、フレームワーク自体に各.NET言語のコンパイラーを組み込んでいます。
基本的に、このシステムの実装には2つの部分があります。
ユーザーがコードをコンパイルできるようにするこれは比較的簡単で、数行のコードでのみ実行できます(エラーダイアログを追加することもできますが、これは、使用方法に応じて、おそらく数十行のコードになります)あなたはそれがなりたいです)。
コンパイルされたアセンブリ内に含まれるクラスを作成して使用するこれは、前のステップより少し難しいです(少しのリフレクションが必要です)。基本的には、コンパイルされたアセンブリをプログラムの「プラグイン」として扱うだけです。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
}
}
}
}
}
}
}
csscript.net
これはある種のラッパーのようです。これは基本的に最小限の実装です。より良い質問は、「csscript.netがこれに対して何をしないのか」ということだと思います。私はcsscriptが何をしているのかわかりませんが、上記のコードが何をしているのかははっきりとわかっています。
IronPython。埋め込み方法の概要は次のとおりです。
PowerShellエンジンは、アプリケーションに簡単に埋め込んでスクリプト化できるように設計されています。実際、PowerShell CLIはエンジンへのテキストベースのインターフェイスにすぎません。
編集:https : //devblogs.microsoft.com/powershell/making-applications-scriptable-via-powershell/を参照してください
ブー語。
C#を試してみませんか?Monoには、特にC#を動的に評価するための素晴らしい新しいプロジェクトがあります。
上記のIronRuby。C#プログラマーとして私にとって興味深いプロジェクトは、MonoでのC#Evalサポートです。ただし、まだ使用できません(Mono 2.2の一部になる予定です)。
私が現在維持しているS#を提案するかもしれません。これは、C#で記述され、.NETアプリケーション用に設計されたオープンソースプロジェクトです。
最初は(2007-2009)http://www.codeplex.com/scriptdotnetでホストされていましたが、最近githubに移動されました。
私はまだこれを試したことがありませんが、かなりクールに見えます:
クライアント用のプラグインを作成したところ、OfficeのVBAのように機能するモジュールでC#コードを記述できるようになりました。
以前Luaを使用したことがあります。Delphiアプリではさまざまなものに組み込むことができます。AdobeのPhotoshop Lightroomで使用されています。
C#自体を使用したスクリプト記述が好きです。現在、2013年には、C#スクリプトのサポートがかなり充実し、そのためのライブラリがますます利用可能になっています。
MonoはC#コードのスクリプト作成に優れたサポートMono.CSharp.dll
があり、アプリケーションにを含めるだけで.NETで使用できます。私が作成したC#スクリプトアプリケーションについては、CShellを確認してください。
また、MicrosoftのRoslynにある「ScriptEngine」も確認してください。ただし、これはCTPのみです。
一部の人々がすでに述べたように、CS-Scriptもかなり以前から存在しています。