PSModule

Bei meinem Projekt "ReportWeb" habe ich überlegt, wie ich Funktionen mehr oder minder dynamisch addieren kann. So bin ich eher spät auf die Module gestoßen, welche ab Powershell Version 2.0 schon vorhanden sind. Hätte ich schon früher deren Potential erkannt, wären einige Powershell-Aufgaben sicher anders umgesetzt worden. In Powershell 1.0 waren nämlich DLLs erforderlich um eine Powershell um eigene Befehle zu erweitern.

Sie konnten aber auch schon immer einfach eine PS1-Datei - erstellen die einfach eine "function" enthielt. Durch den Aufruf dieses Skripts haben Sie dann die Funktion in der aktuelle Session definiert. Problem hierbei war aber, dass alle "Variablen" in diesen Funktionen ebenfalls in ihrer Session definiert waren. Überschneidungen bei Namen können zu unerwarteten Ergebnissen führen. Zudem können die Funktionen eigentlich nicht mehr entfernt werden. Dieses Verfahren wird oft auch als "Dot Source" beschrieben.

Oder sie haben von einem Powershell-Skript ein anderes Skript aufgerufen. Hierbei war das Problem dann aber, dass eine mehrfache Verwendung immer wieder geladen werden muss. Schön ist das nicht.

Basics  -Wo und wie

Powershell 2 Module sind einem Powershell Script sehr ähnlich. Sie haben den gleichen Aufbau und können mit den bekannten Editoren erstellt werden und haben einige deutliche Vorteile:

Interessant ist, dass die Funktionen z.B. z.B. eigene Variablen und Objekte verwenden können und diese zwischen den Aufrufen bestehen bleiben. Es ist damit zwar noch keine Klasse, weil ein Modul nur einmal eingebunden werden kann, aber für viele Zwecke wird oft nur ein "Objekt" verwendet.

Laden, Finden, Sharen

Wenn Sie ein Modul mit "Add-Module" hinzufügen und sie keinen absoluten Pfad mit angeben, dann sucht die Powershell ein PSModulePath ab:

PS C:\> $env:psmodulepath C:\Users\fcarius\Documents\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules\;C:\Program Files\Common Files\Microsoft Lync Server 2010\Modules\

Die Powershell beobachtet dabei die Daten in der folgenden Reihenfolge:

Ein Modul wird aber immer nur einmal geladen. Gerade wenn Sie Module entwickeln und ändern müssen Sie das Modul in der Testumgebung immer erst entladen und neu laden oder mit "-force" laden. Bestehende Variablen im Modul werden dann aber natürlich zurück gesetzt.

Wenn man gewissenhaft Module in sich abgeschlossen entwickelt, z.B. auch unabhängig von globalen Voraussetzungen, dann können Sie sich eine Bausteinsammlung aufbauen, die sie immer wieder verwenden können.

Module können sogar verschachtelt werden. Schon fast wie wenn Sie ein bestehendes Module durch eigene Funktionen bereichern können. Wenn ein fertiges Modul ihnen zu viele Parameter hat, können Sie einfach ein eigenes Modul nutzen, welche das andere Modul einbindet und ihre lokal gültigen Parameter vorausfüllt. Dabei sind nur die Commandlets des Hauptmoduls erreichbar.

Beispiel

Es gibt viele Beispiele im Internet, die den Einsatz von Modulen zeigen. Ich möchte mich daher auf eine einfaches Modul als Muster beschränken:

# Modulsample to explain basic modules
[long]$script:test=0  # initialize Variable

function add-Modulsample {
	$script:test++
	write-host "Module1: Sub Plus-Modulsample done: Test=$script:test"
}

function get-Modulsample {
	$script:test
	write-host "Module1: Sub Get-Modulsample done: Test=$script:test"
}

function Set-Modulsample ($value ){
	$script:test = $value
	write-host "Module1: Sub Set-Modulsample done: Test=$script:test"
}

# Es ist ratsam am Ende eine Ausgabe zu generieren. Diese wir beim Laden des Moduls angezeigt
write-host "modulsample: Ready to Use"

Auf ein paar Dinge möchte ich hier hinweisen.

Experimentieren Sie einfach etwas mit Modulen und verändern Sie den Beispielcode, um das unterschiedliche Verhalten zu sehen. Vergessen Sie aber nicht nach Änderungen am Modul diese neu zu laden.

Module und Klassen

Noch sind Module einfach weitere Powershell-befehle, die Sie nach dem Import nutzen können. Aber damit sind es noch keine Klassen, die mehrfach instanziert werden können und ihre internen Wert und Funktionen und nach extern erreichbare Properties und Methoden haben. Und genau das geht auch mit Modulen. Sie müssen Sie beim "Import-Module" oder New-Module einfach mit "-AsCustomObject" aufrufen. Damit werden aus den Funktionen entsprechende Methoden und exportierte Variablen werden zu Properties.

Hierbei zeigen sich aber zwei Probleme:

Mit beiden Einschränkungen kann man natürlich leben auch wenn Sie nicht schön sind. Um aber nicht in Konflikt mit anderen Namen zu kommen, sollte so ein Modul dann immer mit dem Parameter "CustomObject" geladen werden.

Weitere Links

Advanced Automation Using Windows PowerShell 2.0
http://channel9.msdn.com/Events/TechEd/NorthAmerica/2011/WSV406
Einstieg in Module ab 38. Minute

Windows PowerShell Modules - Patterns and Practices - Dan Harman
http://www.youtube.com/watch?v=yDmkXZVD55w
US TEC 2011 PowerShell Deep Dive conference, Windows PowerShell Program Manager Dan Harman

Die PowerShell Module 4:28Min
http://www.youtube.com/watch?v=Tmf7EFUXEhg&feature=related

Keywords:Powershell Module