Autodiscovery und Export-ModuleMember
Beim Starten des Powershell-Prozesses ist Autodiscovery dafür verantwortlich zu ermitteln, welche Funktionen, Variablen und Aliase in einem Skript vorliegen und diese in Powershell sichtbar zu machen, ohne das Modul-Skript sofort auszuführen. Es gibt allerdings einige Unterschiede im Verhalten zwi-schen Modulen mit und ohne Modulmanifest, die ziemlich viel Verwirrung stiften können.
Autodiscovery funktioniert automatisch und macht, wie wir bereits gesehen haben, alle Funktionen aus dem Skriptmodul sichtbar. Wenn Sie in Ihrem Skriptmodul aber Variablen oder Aliase anlegen, die glo-bal in der Powershell genutzt werden sollen, werden Sie feststellen, dass Aliase erst in der Konsole sichtbar sind und benutzt werden können, nachdem Sie eine Funktion aus Ihrem Skript aufgerufen ha-ben. Variablen sind selbst nach dem Aufrufen des Skriptes nicht sichtbar! Zur Demonstration speichern Sie dazu folgendes Skript in Ihrem persönlichen Profilordner als DemoModule.psm1 und starten Sie einen neuen Powershell-Prozess.
Wenn die Funktion Test-Modulemember nicht aufgerufen werden kann, und Dateiname, Modulordernname und Modulpfad korrekt sind, prüfen Sie Ihre Ausführungsrichtlinie. Wenn die Ausführung von Powershell-Skripten verboten ist, können auch keine Skriptmodule ge-laden werden.
Function Test-ModuleMember { param(
[Parameter()]
$UserName = "Holger"
)
"$Username ist da!"
}
New-Alias -Name TMM -Value Test-ModuleMember
$DefaultPassword = "Passw0rd"
Wenn Sie versuchen, Test-ModuleMember über das Alias TMM zu starten, werden Sie feststellen, dass das Alias nicht vorhanden ist, genauso wenig wie die Variable $DefaultPassword. TestModuleMember lässt sich dagegen ausführen. Sobald Test-Modulemember einmal gestartet wurde, ist plötzlich auch das Alias verfügbar, aber die Variable bleibt weiterhin verschwunden.
Dieses Verhalten hängt damit zusammen, dass Autodiscovery nur Elemente aus Ihrem Modul an Pow-ershell weitergibt, die explizit exportiert werden, wobei Funktionen aus einem Skriptmodul standardmä-ßig exportiert werden. Aliase werden nach dem Aufrufen der ersten Funktion verfügbar, weil Powershell dann das komplette Skriptmodul zum ersten Mal wirklich ausführt und alle Aliase global erstellt. Varia-
blen werden explizit nicht sichtbar, weil Variablen in einem Skriptmodul weiterhin als lokale Variablen ausgeführt werden.
Wenn Sie Aliase oder Variablen exportieren lassen wollen, müssen Sie das explizit angeben, indem Sie in Ihrem Skriptmodul den Befehl Export-ModuleMember aufrufen.
<# Hier steht der Skriptcode #> Export-ModuleMember -Function * Export-ModuleMember -Alias * Export-Modulemember -Variable *
Ohne Export-Modulemember sind Elemente durch Autodiscovery nicht ermittelbar. Die Ausnahme sind Funktionen, die Powershell automatisch exportiert, solange Export-ModuleMember im Skript nicht auf-gerufen wird. Daher sind die Funktionen, die im Skriptmodul Helperfunctions.psm1 angelegt sind, trotzdem sichtbar gewesen. Aliase werden erst dann sichtbar, wenn sie explizit exportiert werden.
Function Write-ReturnArrayFromScriptblock
{
# hier steht der Funktionscode
}
Function Test-ParameterValueFromPipeline
{
# hier steht der Funktionscode
}
$ExecutionTime = Get-Date
New-Alias -Name WRA -Value Write-ReturnArrayFromScriptblock New-Alias -Name PVF -Value Test-ParameterValueFromPipeline
Export-ModuleMember -Function * Export-ModuleMember -Alias * Export-ModuleMember -Variable *
Sie können auch Variablen exportieren, allerdings verhalten sich diese noch einmal anders. Exportierte Variablen werden nämlich durch den Autodiscovery nicht sichtbar, sondern erst bei der ersten Ausfüh-rung des Skriptmoduls als globale Variable angelegt. Das heißt, dass exportierte Variablen trotz des Ex-ports erst nach dem ersten Ausführen Ihres Skriptmoduls erzeugt werden. Das ist leider alles andere als konsistent.
Achten Sie darauf, dass Sie, sobald Sie Export-ModuleMember verwenden, auch Ihre Funktionen ma-nuell exportieren müssen, da der automatische Funktionsexport nur solange funktioniert, wie Sie Ex-port-ModuleMember nicht verwenden.
Wenn Sie eine Manifest-Datei verwenden, können Sie in der Manifest-Datei ebenfalls angeben, welche Elemente exportiert werden sollen. Hier noch einmal der Ausschnitt aus der Manifest-Datei:
# Aus diesem Modul zu exportierende Funktionen. FunctionsToExport = '*'
# Aus diesem Modul zu exportierende Cmdlets. CmdletsToExport = '*'
# Die aus diesem Modul zu exportierenden Variablen VariablesToExport = '*'
# Aus diesem Modul zu exportierende Aliase. AliasesToExport = '*'
Die Manifest-Datei kann aber nur Elemente exportieren, die über Export-Modulemember bereits sichtbar sind. Die Cmdlets, Funktionen, Variablen und Aliase müssen im Skriptmodul exportiert sein, damit sie über das Manifest gesteuert werden können!
Das heißt, dass alle nach außen sichtbaren Funktionen, Aliase und Variablen im Skriptmodul und, sobald Sie eine Manifest-Datei benutzen, auch in dieser explizit zum Export angegeben werden müssen. Ver-gessen Sie Export-Modulemember im Skript anzugeben, können Sie Aliase und Variablen im Manifest nicht mehr exportieren! Aus Performance-Gründen sollten Sie außerdem alle Funktionen und Aliase
namentlich exportieren, selbst wenn Sie alle Funktionen Ihres Skriptes exportieren wollen. Das be-schleunigt den Autodiscovery-Prozess deutlich!
Helperfunctions.psm1 könnte also z.B. so aussehen:
Function Write-ReturnArrayFromScriptblock
{
# hier steht der Funktionscode
}
Function Test-ParameterValueFromPipeline
{
# hier steht der Funktionscode
}
$ExecutionTime = Get-Date
New-Alias -Name WRA -Value Write-ReturnArrayFromScriptblock New-Alias -Name PVF -Value Test-ParameterValueFromPipeline
Export-ModuleMember -Function Write-ReturnArrayFromScriptBlock,` Test-ParameterValueFromPipeline
Export-ModuleMember -Alias WRA,PVF
Export-ModuleMember -Variable ExecutionTime
Wie Sie hier sehen, können Sie auch einzelne Funktionen, Aliase oder Variablen namentlich angeben. Sie können sogar Wildcards in Namen für den Import verwenden. Dadurch wird es möglich, z.B. eine ganze Kategorie von Daten zu exportieren:
Export-ModuleMember -Function Get-*