Blogger :
MSDN Blogs
All posts :
All posts by MSDN Blogs
Category :
SAPscript
Blogged date : 2007 Jun 26
Schon einmal versucht, eine eigene Applikation per Skript automatisierbar zu machen? Auf meinem TechTalk letzten Monat habe ich unter anderem gezeigt, wie einfach Derartiges zu bewerkstelligen ist. Bietet doch das .NET Framework erfreulicherweise alles was es braucht um .NET Sprachen selbst zu kompilieren. Ja, wer möchte kann mit den Frameworkklassen auch recht einfach eigene Parser, Compiler etc. implementieren. Und es sind wirklich nur ein paar wenige Zeilen...
Dreh- und Angelpunkt meines kleinen Beispiels ist die CSharpCodeProvider-Klasse. Solche Codeprovider werden für jede .NET Sprache implementiert und sind Startpunkt für Parser-, Codegenerierungs- und Compileoperationen.

Im ersten Schritt möchte ich einfach nur den Code in der Textbox kompilieren und ausführen. Damit ich im Ergebnis nichts konvertieren oder auf Schnittstellen casten muß, mache ich es mir ganz einfach und überschreibe nur mal die ToString()-Methode, die ich an jedem Objekt aufrufen kann. Damit schon genug. Bei Klick auf "Ausführen" compiliere ich also den fraglichen Code, nehme das Ergbnis, erzeuge daraus ein Objekt und rufe einfach ToString() auf. Das sieht dann so aus:
1 CSharpCodeProvider cprov = new CSharpCodeProvider();
2
3 CompilerParameters cparams = new CompilerParameters();
4 cparams.GenerateExecutable = false; //keine Datei erzeugen...
5 cparams.GenerateInMemory = true; //...sondern alles im Speicher ablegen
6 cparams.ReferencedAssemblies.Add("System.Windows.Forms.dll"); //ggf. Assemblies referenzieren
7
8 CompilerResults results = cprov.CompileAssemblyFromSource(cparams, new string[] { textBox1.Text }); // los gehts
9
10 if (results.Errors.Count==0) {
11 object o = results.CompiledAssembly.CreateInstance("myclass");
12 o.ToString(); //jetzt wird unser "Skriptcode" ausgeführt
13 }
Simpel, oder?
Was hier jedoch noch fehlt ist Interaktion mit der Mutterapplikation. Vielleicht möchte man dem Skriptschreiber ja ein Objektmodell bieten mit dem man die Applikation automatisieren kann? Nichts leichter als das. In meiner Beispielapplikation wird das gleich als nächstes gemacht. Trick hier ist, eine Schnittstellen-DLL zu erstellen, die in einer Aufruf-Methode genau die Parameter durchreicht, die wir automatisierbar machen wollen:
public interface IExecutable
{
void Execute(Form myform);
}
In meinem Beispiel reiche ich einfach die aktuelle Form herein, so kann mein Skript vollständig darauf zugreifen. Nun wird als nächstes natürlich auch eine entsprechende Referenz für den Compilercode fällig. Wir ergänzen also die Parameterdefinition um eine weitere Zeile:
cparams.ReferencedAssemblies.Add("Schnittstellen.dll");
Jetzt muß das Script natürlich unsere Schnittstelle implementieren und uns damit die Möglichkeit bieten, die Methode später aufzurufen. Unser Aufrufcode wiederum wird um einen entsprechenden Cast erweitert:
1 if (results.Errors.Count == 0)
2 {
3 object o = results.CompiledAssembly.CreateInstance("myclass");
4 IExecutable iexec = o as IExecutable;
5 if (iexec == null)
6 {
7 MessageBox.Show("Das Objekt implementiert die Schnittstelle IExecutable nicht!");
8 }
9 else
10 {
11 // Schnittstelle aufrufen
12 iexec.Execute(this);
13 }
14 }
Last but not least kann man übrigens auch ohne weiteres auf die Idee kommen, dem Benutzer die Möglichkeit zu geben einfach nur Codefragmente einzugeben und diese dann programmatisch für die Kompilierung in eine vorbereitete Codedatei einzufügen. Damit ist es sehr einfach möglich, beispielsweise Formeln zur Berechnung etc. separat kompiliert auszuführen. Mein kleines Beispiel zeigt auch das.
Und wofür kann man das nun alles brauchen? Nunja: Mathematische Formeln, Userscripts, Adminscripts, Plugins, ... Nur ein paar Beispiele.
Viel Spaß beim Testen!
Hier gehts zum Download...