Autor: Holger Schwichtenberg , zur Startseite von Windows-Scripting.de

Startseite
Download Version 1.1
Version history 
  Documentation in Englisch (PDF)

Der DOTNET Scripting Host  (DSH) ist ein Active Scripting Host für das .NET Framework, der die wesentlichen Funktionen des ActiveX Scripting-basierten Windows Script Host (WSH) für die Common Language Runtime nachbildet:

·         Start von Skripten an der Kommandozeile

·         Verpacken von Skripten in einer XML-Datenstruktur

·         Entfernte Ausführung von Skripten (Fernausführung, engl. Remoting)

Darüber hinaus bietet der DSH gegenüber dem WSH auch einige erweiterte Funktionen wie die Protokollierung in eine Textdatei oder ein Windows-Ereignisprotokoll.

Der DSH arbeitet nicht mit Script for .NET/Visual Studio for Applications (VSA), sondern verwendet die in der .NET Framework Class Library (FCL) integrierten Compiler direkt. Der DSH nutzt diese Compiler, um eine übergebene Quellcodedatei zu kompilieren und dann die erzeugte Assembly auszuführen. Die Assembly wird dabei im Speicher erzeugt und (im Standard) nicht auf die Festplatte geschrieben. Der Nutzer des DSH kann daher nicht erkennen, dass das Programm nicht interpretiert, sondern kompiliert wird. Derzeit unterstützt der DSH keine anderen .NET-fähigen Sprachen außer Visual Basic .NET, C# und JScript .NET. Die optionale Speicherung der erzeugten Assembly ist möglich.

 

  Dateiformat

Der DSH verwendet als Dateiformat XML. Das ist sinnvoll, weil neben dem eigentlichen Script auch noch Zusatzinformationen wie der Name der verwendeten Sprachen und der referenzierten Assemblies an den Compiler übergeben werden müssen.

Ein Skript-Dokument kann mehrere einzelne Skripte enthalten, die sequentiell ausgeführt werden.

XML-Element

Erlaubte Häufigkeit

Erläuterung

<?xml version="1.0" encoding="ISO-8859-2"?>

1

Processing Instruction

<scriptdoc>

1

Wurzelelement, das den Rahmen um alle untergeordneten Elemente bildet.

Mit dem Attribut process="1" wird festgelegt, dass eventuell schon vorher laufende Instanzen dieses Skriptdokuments gewaltsam beendet werden.

<comment>

0..N

Kommentar-Element, wird vom DSH ignoriert.

<references>

0/1

Fasst ein oder mehrere <assembly> -Elemente zusammen.

<assembly>

0..N

Definiert eine zu referenzierende Assembly.

<log>

0/1

Legt fest, welche Meldungen des DSH in ein Ereignisprotokoll und/oder eine Textdatei geschrieben werden sollen.

Attribut

Erläuterung

error

Optionales Attribut

Sofern das Attribut existiert und nicht auf "NO" steht, wird ein Protokolleintrag im Fehlerfall erzeugt.

success

Optionales Attribut

Sofern das Attribut existiert und nicht auf "NO" steht, wird ein Protokolleintrag bei erfolgreicher Beendigung eines Skripts erzeugt.

start

Optionales Attribut

Sofern das Attribut existiert und nicht auf "NO" steht, wird ein Protokolleintrag beim Start eines Skripts erzeugt.

<eventlog>

0/1

Unterelement von <log> .

Legt im Attribut name den Namen des Ereignisprotokolls fest, in das die Einträge geschrieben werden sollen. Außer den Standardprotokollen (z.B. Application, System und Security) können auch beliebige eigene Protokollnamen verwendet werden. Der DSH legt automatisch ein entsprechendes Ereignisprotokoll an.

<logfile>

0/1

Unterelement von <log> .

Legt im Attribut name den Pfad einer Textdatei fest, in die die Protokolleinträge geschrieben werden sollen.

<script>

1..N

Quellcode des Skripts. Es kann beliebig viele <script> -Elemente geben. Die Skripte werden nacheinander in der Reihenfolge ihres Auftretens in der Datei abgearbeitet.

Attribut

Erläuterung

Name

Optionales Attribut

Name für das Skript

language

Notwendiges Attribut

Mögliche Attributwerte:
"VB.NET" , "CSharp" und "JS.NET" .

startClass

Optionales Attribut

Name der Klasse, deren Unterroutine Main() den Startpunkt des Skripts bildet. (Im Standard wird nach einer Klasse mit Namen Main gesucht, also Main::Main() .)

Tabelle 1.1: XML-Elemente in DSH-Skripten

Die Dateiextension ist beliebig. Vorgesehen ist aber die Dateiextension .dsh.

Beispiel

Beispiel

Das folgende Listing zeigt ein Beispiel mit drei Skripten:

·         Das erste Skript (CSharp) gibt Hello World aus.

·         Das zweite Skript (VB.NET) liest die Zeichenkette "Hello World" aus einer XML-Datei aus.

·         Das dritte Skript (VB.NET) listet die übergebenen Parameter auf.

<?xml version="1.0" encoding="ISO-8859-2"?>

<scriptdoc process="1">

 <comment>

Demo-Skript von Holger Schwichtenberg

</comment>

<references>

<assembly>system.xml.dll</assembly>

<assembly>System.DirectoryServices.dll</assembly>

<assembly>system.data.dll</assembly>

</references>

<log error="YES" success="YES" start="YES">

<eventlog1 name="Scripting"/>

<logfile1 name="e:\log.txt"/>

</log>

<!-- ****************************************** -->

<script name="FirstScript" language="CS" startClass="Scripting.StartKlasse">

using System;

namespace Scripting

{

       class StartKlasse

       {

             static void Main(string[] args)

             {

                    Console.WriteLine("FirstSkript: Hello World!");

             }

       }

}

</script>

<!-- ****************************************** -->

<script name="SecondScript" language="vb.net">

<![CDATA[

Imports System.XML

Imports System

Module Main

    Sub Main()

         

        ' --- Test XML

       Dim d as new XmlDocument

        d.loadxml("<test><message>Hello World!</message></test>")

       Console.Writeline("SecondSkript: Message from the document: " & d.SelectSingleNode("*//message").InnerText)

     

     End Sub

End Module

]]>

</script>

<!-- ****************************************** -->

<script name="ThirdScript" language="vb.net">

<![CDATA[

Imports System

Module Main

    Sub Main(args as string())

     Console.WriteLine("ThirdScript: List auf script arguments:")

         ' --- Argumente ausgeben

             Dim s as string

             for each s in args

                    console.writeline("- "& s)

           next

    End Sub

End Module

]]>

</script>

</scriptdoc>

Listing: Beispiel für ein DSH-Skript

Aufbau des Skripts

Main/(

Ein Skript muss einen eindeutigen Einsprungpunkt besitzen. Dazu muss ein Skript aus mindestens einer Klasse (ein Modul in Visual Basic ist eine spezielle Form einer Klasse) mit einer statischen Methode bestehen, die Main() heißt. Optional sind weitere Attribute und Methoden in dieser Klasse oder weitere Klassen mit Attributen und Methoden möglich.

startClass

Der Name der Klasse, die den Einsprungpunkt bildet, ist frei wählbar (definierbar durch das XML- Attribut startClass im <script> -Element). Der Name der Methode ist nicht frei wählbar, er lautet immer Main() . Es gibt zwei mögliche Signaturen für Main() :

·         Sub Main()

·         Sub Main(args as string())

Parameter

Im letzteren Fall empfängt Main()  vom DSH die dem Skript übergebenen Kommandozeilenparameter in einem Array of String . Andere Parameter sind bei Main() nicht erlaubt. Der Name, der dem Parameter gegeben wird, ist frei wählbar.

Module Main

    Sub Main(Argumente as string())

    ' …

    End Sub

End Module

Listing: Grundgerüst für ein DSH-Skript

Start eines Skripts

dsh.exe

Man startet ein DSH-Skript, indem man dsh.exe mit dem Dateinamen aufruft.

H:\DSH>dsh.exe testscript.dsh

----------------------------------

DOTNET Scripting Host (DSH)

Version: 1.0

(C) Holger Schwichtenberg 2002

http://www.windows-scripting.com

----------------------------------

FirstSkript: Hello World!

SecondSkript: Message from the document: Hello World!

ThirdScript: List auf script arguments:

- ../demos/testscript.dsh

  Kommandozeilenparameter

Kommandozeilenparameter

Ebenso wie der WSH unterstützt der DSH drei Arten von Kommandozeilenparametern:

·         Name (inklusive Pfad) des aufrufenden Skripts. Der erste Parameter, der nicht mit einem Slash (/ ) beginnt, wird als Dateiname betrachtet.

·         Parameter für den DSH selbst. Diese beginnen mit einem doppelten Slash (// ).

·         Parameter für das aufgerufene Skript. Alle Parameter, die nicht mit einem doppelten Slash (// ) beginnen, werden dem aufgerufenen Skript als Parameter übergeben. Das Skript erhält also auch seinen eigenen Dateinamen. Dieser wird immer als erster Parameter an das Skript übergeben.

Parameter

Erläuterung

//ABOUT

Liefert Informationen über den DSH.

//HELP

Zeigt Hilfe zu den Kommandozeilenoptionen an.

//EN

Alle Ausgaben in englischer Sprache.

//DE

Alle Ausgaben in deutscher Sprache.

//S

Silent. Der DSH macht – wenn kein Fehler auftritt – keine Ausgaben außer denen, die das Skript selbst erzeugt.

//V

Verbose. Der DSH ist sehr "geschwätzig" und liefert zusätzliche Ausgaben über die Verarbeitung der XML-Datei und den Übersetzungsvorgang.

//ERRORGUI

Legt fest, dass Fehlermeldungen des DSH als Dialogboxen angezeigt werden sollen.

//SUCCESSGUI

Legt fest, dass nach erfolgreicher Ausführung aller Skripte eine Dialogbox angezeigt werden soll.

//OUT:Verzeichnis

Legt fest, dass die kompilierten Assemblies im Dateisystem in dem angegebenen Verzeichnis gespeichert werden sollen.

//SERVER:Portnummer

Startet den DSH als Server (Listener). Der DSH wartet auf dem angegebenen Port auf (Fern-)Aufrufe von einer anderen Instanz des DSH. Der DSH-Listener ist so lange aktiv, bis der Prozess beendet wird.

//COMPUTER:Name

Name oder IP-Adresse des Computers, auf dem das Skript gestartet werden soll. Ohne diese Angabe wird das Skript auf dem lokalen Computer gestartet.

//PORT:Portnummer

Portnummer der entfernten DSH-Instanz. Ohne diese Angabe wird das Skript auf dem lokalen Computer gestartet.

//HTTP

Als Protokoll für das Remote Scripting wird HTTP anstelle von TCP verwendet. Diese Option kann sowohl in Kombination mit //COMPUTER als auch //SERVER verwendet werden. Auch im Fall der Verwendung von //HTTP muss zusätzlich //PORT angegeben werden.

Tabelle: Kommandozeilenparameter des DSH 1.0

Eingebaute Objekte

Intrinsic Objects, FCL

Der DSH besitzt keine speziellen eingebauten Objekte (Intrinsic Objects). Den Skripten stehen alle Klassen der .NET Framework Class Library (FCL) zur Verfügung – genauso wie einem "normalen" .NET-Programm auch.

Assembly-Referenzen

Um eine Klasse zu nutzen, muss die Assembly, die diese Klasse implementiert, als Referenz hinzugefügt werden. Dazu muss im Element <assembly> der Name der Datei, die die Assembly enthält, angegeben werden. Die Datei muss entweder im Global Assembly Cache (GAC) oder im gleichen Verzeichnis wie die DSH.exe liegen (nicht im gleichen Verzeichnis wie das Skript!).

Es ist sinnvoll, aber nicht notwendig, die zu verwendenden Namespaces mit Imports oder using einzubinden.

Assembly-Persistenz

Speicherung des erzeugten Assembly

Mit der Option //OUT:Verzeichnis kann die erzeugte Assembly im Dateisystem persistent gemacht werden, also das Skript in einer kompilierten Form abgelegt werden. Dieses Kompilat ist MSIL-Code, der direkt gestartet werden kann.

Die Assembly erhält dabei den Namen des Skripts innerhalb des Skriptdokuments. Als Dateiextension wird .exe angehängt. Nach //OUT: muss das Verzeichnis angegeben werden, in dem die Assembly abgelegt werden soll. Wenn dort schon eine gleichnamige Datei existiert, wird diese ohne Warnung überschrieben. Das angegebene Verzeichnis muss existieren, sonst kommt es zu einer Fehlermeldung.

Wenn das Skriptdokument mehrere Skripte enthält, werden mehrere einzelne Assemblies erzeugt.

Fernausführung von Skripten

Remoting

Der DSH unterstützt Remoting. Man kann den DSH auf einem Computer aufrufen und ihn anweisen, ein lokal erreichbares Skript auf einem entfernten Computer auszuführen. Dies entspricht dem Konzept des Remoting beim Windows Script Host (WSH). Anders als beim WSH ist jedoch auf dem Client selbst kein Skript notwendig: Das Remoting wird durch eine Kommandozeilenoption des DSH initiiert.

Auf dem Server muss eine Instanz des DSH laufen, die zuvor auf einem bestimmten Port gestartet wurde. Auch dies ist anders als beim WSH, entspricht jedoch dem Remoting-Konzept des .NET Frameworks.

TCP/IP

Die Kommunikation zwischen Client und Server erfolgt in DSH über TCP/IP über einen frei wählbaren Port.

Start des Servers

Der Server wird gestartet durch die Option //server unter Angabe einer freien Portnummer. Wenn der Port noch frei ist, beginnt die Überwachung des Ports auf eingehende Aufrufe.

H:\DSH>dsh.exe //server:9999

DOTNET Scripting Host (DSH)

Version: 1.0

(C) Holger Schwichtenberg 2002

http://www.windows-scripting.com

Starting DSH listener on port 9999...

Press enter to stop this process.

Wenn der Port schon belegt ist, erscheint folgende Fehlermeldung:

ERROR: Normalerweise darf jede Socketadresse (Protokoll, Netzwerkadresse oder Anschluss) nur jeweils einmal verwendet werden.

Das "Normalerweise" in diesem Satz wirkt fehlplatziert. Dies ist jedoch eine in der .NET Framework Class Library hinterlegte Meldung.

Start des Client

Der Client wird ganz normal unter Angabe eines Skriptnamens gestartet. Zusätzlich ist Folgendes festzulegen: der Computername (oder die IP-Adresse) nach //computer und der Port (//port ), auf dem der entfernte DSH "lauscht".

dsh.exe testscript.dsh //computer:byfang //port:9999 //v

So sieht ein erfolgreicher Aufruf aus:

DOTNET Scripting Host (DSH)

Version: 1.0

(C) Holger Schwichtenberg 2002

http://www.windows-scripting.com

Im "geschwätzigen" Modus (//V) gibt es mehr Infos:

DOTNET Scripting Host (DSH)

Version: 1.0

(C) Holger Schwichtenberg 2002

http://www.windows-scripting.com

Loading Script Document...testscript.dsh

Connecting to Client byfang:9999...

Calling Remote DSH...

Script Document testscript.dsh finished successfully!

Der Client erhält die Fehlermeldung, wenn die Ausführung nicht erfolgreich war:

DOTNET Scripting Host (DSH)

Version: 1.0

(C) Holger Schwichtenberg 2002

http://www.windows-scripting.com

Loading Script Document...testscript.dsh

Connecting to Client byfang:9999...

Calling Remote DSH...

COMPILE ERROR in Script at Line # 10: BC30451:Name 'irgendwo1' is not declared.

COMPILE ERROR in Script at Line # 15: BC30451:Name 'xyz' is not declared.

Ausgaben auf dem Server

Bitte beachten Sie, dass alle Bildschirmausgaben des übermittelten Skripts auf dem Server im DOS-Fenster des Serverprozesses stattfinden!

DOTNET Scripting Host (DSH)

Version: 1.0

(C) Holger Schwichtenberg 2002

http://www.windows-scripting.com

Starting DSH listener on port 9999...

Press enter to stop this process.

FirstSkript: Hello World!

SecondSkript: Message from the document: Hello World!

ThirdSkript: List auf script arguments:

- testscript.dsh

- /abc

- testoption

Wenn der Server mit der Option //v gestartet wird, informiert er sehr ausführlich:

DOTNET Scripting Host (DSH)

Version: 1.0

(C) Holger Schwichtenberg 2002

http://www.windows-scripting.com

Starting DSH listener on port 9999...

Press enter to stop this process.

Receiving call...

Parsing document...

Parsing References...

Adding References: system.xml.dll

Adding References: System.DirectoryServices.dll

Adding References: system.data.dll

Parsing Script Document...

usw.

Limitationen

Fehlende Features

Derzeit beim DSH (noch) nicht möglich ist,

  • dass sich Skripte innerhalb einer Skriptdatei gegenseitig aufrufen.
  • dass Skripte andere Skriptdokumente referenzieren. Referenzen sind nur auf Assemblies möglich.

dass beim Remoting HTTP und SOAP  verwendet werden.