Task 'Prozess ausführen' mit Ereignishandler

Dieser Artikel gibt einen Einblick in die Verwendung des Task 'Prozess ausführen' und die Möglichkeit über einen Ereignishandler (Eventhandler) Ausgabe und Fehler dieses Task zu verarbeiten.

Grundlagen Task 'Prozess ausführen'

Mit Hilfe dieses Task ist es möglich einen weiteren Prozess zu starten, wobei dies über eine ausführbare Datei (*.exe, *.com, *.bat, *.cmd) erfolgt. Weiterhin kann hier auch das Arbeitsverzeichnis angegeben werden.

Falls man Argumente an einen Prozess übergeben will, schreibt man diese einfach in die Eigenschaft "Arguments". Falls ich dies nicht statisch tun möchte, sondern mit einer Variablen dynamisch belegen will, kann ich dies über die "Ausdrücke" definieren.

Die "StandardInputVariable" übergibt den Inhalt der dort angegebenen Variablen an den Standard-Input des Prozesses. Das heißt, der Prozess muss explizit vom Standard-Input diese Informationen lesen.

Interessant ist am Ende der Liste die Eigenschaft "Windows Style", welche die Darstellung des neuen Fensters angibt, in welchem der Task gestartet wird. In der Regel stehen in dem Fenster auch die Ausgaben des Prozesses und die Fehlermeldungen.

Starte ich das SSIS-Paket aber nicht interaktiv im Business Intelligence Development Studio (BIDS), sondern z. B. per Job, dann werde ich wohl kaum in den Genuss dieser Ausgaben kommen, wenn ich sie nicht umleiten kann. Deshalb gibt es ausserdem noch die Eigenschaften

  • StandardOutputVariable
  • StandardErrorVariable

Standard Output und Error im Ereignishandler

Diese beiden Variablen ermöglichen mir das Ergebnis des Task 'Prozess ausführen' weiter zu verarbeiten. Man könnte dies statisch im Paket codieren und diese Werte z. B. in eine Tabelle schreiben. Etwas eleganter ist dies über einen Ereignishandler möglich. Wann immer gewisse Ereignisse ausgelöst werden, wird dieser Handler aufgerufen. So kann ich über einen Handler auch die Ausgabe mehrerer Prozesse verarbeiten, ohne dies mehrfach zu codieren. Ich muss lediglich immer den StandardOutput und/oder StandardError in eine Variable umleiten, und diese in die Lage versetzen diesen Handler auszulösen. Der Ereignishandler sollte dann auch nicht für einen einzelnen Task definiert werden, sondern auf Paketebene.

Das Vorgehen ist also folgendes:

  1. Definition der Variablen, die bei Änderung ein Ereignis auslösen
  2. Definition des Task 'Prozess ausführen'
  3. Codierung eines einzigen Ereignishandlers, der auf solche Ereignisse reagiert

Definition der Variablen

Man öffnet die Registerkarte für die Variablen (z. B. über den Menüpunkt SSIS->Variablen) und legt die beiden Variablen an:

  • StandardError
  • StandardOutput

Anschliessend öffnet man die Eigenschaften der Variablen und setzt dort die Eigenschaft "RaiseChangedEvent" auf True. Alternativ verwendet man das kleine Icon im Variablen-Fenster mit dem Tool-Tip "Variablenspalten auswählen" und selektiert dort auch die Spalte "Ereignis bei Variablenwertänderung auslösen". Damit hat man zukünftig direkten Zugriff auf diese Eigenschaft und kann sie auch komfortabel ändern.

Definition des Task 'Prozess ausführen'

Aus der Toolbox zieht man den Task 'Prozess ausführen' in die Ablaufsteuerung und öffnet ihn danach zur Bearbeitung.

Hier werden dann die beiden Variablen eingetragen.

Codierung des Ereignishandlers

Damit ist die Vorbereitung abgeschlossen und das eigentliche Herzstück der Verarbeitung kann erstellt werden. In der Lasche "Ereignishandler" wählen wir unter "Ausführbare Datei" das Paket aus und als "Ereignishandler" nehmen wir das Ereignis "OnVariableValueChanged". Durch einen Klick auf den blau unterstrichenen Text erstellen wir einen Ereignishandler.

Die weitere Vorgehensweise ist ähnlich wie bei der Ablaufsteuerung. Man zieht einfach aus der Toolbox einen Task in die freie Fläche und konfiguriert diesen. Für diesen Handler wollen wir zuerst einen "Skripttask" verwenden. Wir öffnen ihn zur Bearbeitung und definieren als Skript-Sprache "Microsoft Visual Basic 2008". Die ReadOnlyVariables werden kommasepariert angegeben und wir verwenden hier die beiden (System-)Variablen "VariableName" und "VariableValue". Man beachte hier die Groß-/Kleinschreibung. Falls man diese nicht selber eintippen will, kann man sie auch aus der Liste auswählen. Diese beiden Variablen gewähren uns den Zugriff auf den Variablen-Namen und den Inhalt der Variablen, die das "OnVariableValueChanged"-Event ausgelöst hat. Bei anderen Ereignishandlern tauchen diese Variablen logischerweise nicht in der Auswahlliste auf.

Danach klickt man auf "Skript bearbeiten" und ersetzt die letzten Zeilen in dem Skript durch den folgenden Code:

Public Sub Main()    Dts.Events.FireInformation(0"Variable Value Changed Event""Variable '" CStr(Dts.Variables("System::VariableName").Value) + _ 
   "'=" CStr(Dts.Variables("System::VariableValue").Value), ""0True)
   Dts.TaskResult ScriptResults.Success End Sub

Dts.Events.FireInformation bewirkt, dass Informationen im Protokoll des Pakets aufgeführt werden. Die Parameter sind

  • informationCode
    Ein Integer welche die Information identifiziert.
  • subComponent
    Ein String, der mehr Details über die Quelle des Events enthält.
  • description
    Der eigentliche Text der Meldung.
  • helpFile
    Der Pfad zum Help file der detaillierte Informationen enthält.
  • helpContext
    Die Identitifkation des Themas im Help file.
  • fireAgain
    Ein Boolean-Wert, der angibt, ob das Ereignis erneut ausgelöst werden kann. Der Wert TRUE gibt an, dass es erneut ausgeführt werden kann.

Dieser Code bewirkt, dass sowohl der Name der Variablen, als auch der Inhalt zu einem String verkettet werden und über DTS.Events.FireInformation im Protokoll des Pakets aufgeführt werden. Nach dem Speichern des Skripts verlassen wir diesen Editor.

Nach der Ausführung des Pakets sieht man das Ergebnis des Task jetzt im Protokoll.
Zur Anzeige des Protokolls gelangt man zum einen über die Lasche "Ausführungsergebnisse", zum anderen kann man das Protokoll über die allgemeine Protokollierung des Pakets z. B. in eine SQL Server-Tabelle schreiben. Hierbei ist aber zu beachten, dass diese Protokollierung in der Regel auf 2048 Zeichen begrenzt ist. Die Zeilen in der Protokollierung lassen sich durch Eingrenzung auf

select *
from sysssislog
where source = 'Skripttask'
and event = 'OnInformation'
anzeigen.

Erweiterte Protokollierung in einer SQL Server Tabelle

Falls man längere Rückgaben in den Variablen erwartet, sollte man sich eine separate Tabelle definieren und diese ebenfalls im Ereignishandler füllen.

CREATE TABLE SSIS_Protokoll 
(
Zeitpunkt DATETIME    DEFAULT GETDATE(),  Variable  VARCHAR(100),  Value     VARCHAR(MAX)
);

Nun ergänzt man den Ereignishandler noch um einen Task 'SQL ausführen' und setzt dort folgendes SQL Statement ein:

Insert into SSIS_Protokoll(Variable, Value) values(?,?)
Über die Parameterzuordnung weist man den beiden Platzhaltern die folgenden Werte zu:

Nun wird also bei jedem Aufruf des Eventhandlers nicht nur ein Eintrag im Protokoll erfolgen, sondern ebenfalls in der zusätzlichen Tabelle ein Eintrag mit Datum und Uhrzeit ergänzt.

Zusatzinformationen

Wer sich über das etwas "merkwürdig" aussehende Icon oben bei der Graphik mit dem Task 'Prozess ausführen' gewundert hat, sei auf die Möglichkeiten des BIDS Helper verwiesen, den man bei codeplex kostenlos herunterladen kann. Dieses Tool ergänzt das BIDS nicht nur um solche netten Infos, sondern ermöglicht auch z. B. das Deployment eines SSIS-Pakets mit einem Klick.

Weiterhin möchte ich an dieser Stelle auf den Artikel von Berthold Neumann zu Variablen in SSIS-Paketen hinweisen. Hier werden einige grundlegende Informationen zur Definition und Verwendung von Variablen gegeben.

  Sourcen.txt