PowerShell Module

PowerShell Module sind ein einfacher und definierter Weg, eine PowerShell Umgebung mit zusätzlichen Befehlen und Commandlets zu erweitern. Allerdings müssen die Namen der bereitgestellten Funktionen natürlich eindeutig sind. Eigene Module sind natürlich auch immer ein Weg, Code einfach zu recyclen

Es gibt aber noch andere Ansätze mit PowerShell modular zu arbeiten, die ich auf  Powershell Modular beschrieben habe.

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:

  • Einbinden und Entfernen bei Bedarf
    Im Gegensatz zu Funktionen aus Skripten können Module zur Laufzeit einfach eingebunden aber auch wieder entladen werden
  • Funktionen exportiert
    Per Default werden alle Funktionen im Modul exportiert. Dies kann aber über "Export-ModuleMember" im Modul selbst gesteuert werden, so das auch "private Funktionen" möglich sind, die aus der Session nicht gefunden und aufgerufen werden können. "Privat" sind diese natürlich nur hinsichtlich des Code. Der Source-Code eines PSM1 ist natürlich einsehbar.
  • Lokale Variablen
    Alle in dem Modul verwendeten Variablen sind per Default nicht außerhalb sichtbar.

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:

  • PSD1 - Manifest-Datei
  • PSM1 - Skriptmodul
  • DLL - Kompiliertes Modul

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 einer PSM1-Datei

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"

Diese Datei kann dann überall liegen und einfach mit "import-module <pfad\dati.psm1> importiert werden.

Auf ein paar Dinge möchte ich hier hinweisen.

  • Ausgabe am Anfang/Ende
    Wenn Sie außerhalb der Funktionen, die später als Commandlet agieren auch Code verwenden, dann wird dieser beim Laden des Module direkt ausgeführt. Es ist ratsam hier eine Bildschirmausgabe vorzusehen.
  • Initialisierung
    Sie können in dem Code aber auch schon erste Komponenten Initialisieren. Ich nutze dies im Beispiel für die Variable "Test", welche durch das Prefix "$Script:" innerhalb des Skripts als global definiert wird. Sie könnten hier aber auch z.B. SQL-Connections, PSSessions oder ADSI-Verbindungen aufbauen.
  • Variablen-Scope
    Sie sehen hier auch die Feinheiten beim Einsatz von Variablen. "Test" ist global bezüglich des Skripts, sonst könnte ich die Werte nicht in den Funktionen verändern. Die Variable ist aber nicht in der Session erreichbar, welche diese Modul importiert.

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:

  • Methoden sind Funktionen mit Parametern
    Es müssen bei der Methode immer alle Parameter angegeben werden. Die bislang gekannte Flexibilität
  • Funktionsnamen "Verb-Noun" funktionieren nicht
    Zwar wird das Modul als Objekt mit der Methode mit dem Namen importiert aber ist nicht aufrufbar. Das ist ja auch nicht weiter schlimm, wenn man die Funktionen der Moduls dann einfach umbenennt.

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