11. Module

Redaktionelle Notiz

Wichtig

Die Windows PowerShell Language Specification 3.0 wurde im Dezember 2012 veröffentlicht und basiert auf Windows PowerShell 3.0. Diese Spezifikation spiegelt nicht den aktuellen Status von PowerShell wider. Es ist nicht geplant, diese Dokumentation zu aktualisieren, um den aktuellen Zustand widerzuspiegeln. Diese Dokumentation wird hier zur historischen Referenz vorgestellt.

Das Spezifikationsdokument ist als Microsoft Word-Dokument im Microsoft Download Center unter: https://www.microsoft.com/download/details.aspx?id=36389 verfügbar. Dieses Word-Dokument wurde hier auf Microsoft Learn zur Darstellung umgewandelt. Während der Konvertierung wurden einige redaktionelle Änderungen vorgenommen, um die Formatierung für die Docs-Plattform zu berücksichtigen. Einige Tippfehler und kleinere Fehler wurden korrigiert.

11.1 Einführung

Wie in §3.14angegeben, ist ein Modul eine eigenständige wiederverwendbare Einheit, mit der PowerShell-Code partitioniert, organisiert und abstrahiert werden kann. Ein Modul kann ein oder mehrere Modulelementeenthalten, die Befehle (z. B. Cmdlets und Funktionen) und Elemente (z. B. Variablen und Aliase) sind. Die Namen dieser Member können für das Modul privat gehalten oder in die Sitzung exportiert werden, in die das Modul importiert wird.

Es gibt drei verschiedene Modultypen: Manifest, Skript und Binärdatei. Ein Manifestmodul ist eine Datei, die Informationen zu einem Modul enthält, und steuert bestimmte Aspekte der Verwendung dieses Moduls. Ein Skriptmodul ist eine PowerShell-Skriptdatei mit der Dateierweiterung .psm1 anstelle von .ps1. Ein binäres Modul enthält Klassentypen, die Cmdlets und Provider definieren. Im Gegensatz zu Skriptmodulen werden binäre Module in kompilierten Sprachen geschrieben. Binäre Module werden von dieser Spezifikation nicht abgedeckt.

Ein binäres Modul ist eine .NET-Assembly (d. h. eine DLL), die für die PowerShell-Bibliotheken kompiliert wurde.

Module können geschachtelt werden, d. h. heißt, ein Modul kann ein anderes Modul importieren. Ein Modul, dem geschachtelte Module zugeordnet sind, ist ein Stammmodul.

Wenn eine PowerShell-Sitzung erstellt wird, werden standardmäßig keine Module importiert.

Wenn Module importiert werden, wird der Suchpfad, mit dem sie gefunden werden, durch die Umgebungsvariable PSModulePath-definiert.

Die folgenden Cmdlets behandeln Module:

11.2 Schreiben eines Skriptmoduls

Ein Skriptmodul ist eine Skriptdatei. Betrachten Sie das folgende Skriptmodul:

function Convert-CentigradeToFahrenheit ([double]$tempC) {
    return ($tempC * (9.0 / 5.0)) + 32.0
}
New-Alias c2f Convert-CentigradeToFahrenheit

function Convert-FahrenheitToCentigrade ([double]$tempF) {
    return ($tempF - 32.0) * (5.0 / 9.0)
}
New-Alias f2c Convert-FahrenheitToCentigrade

Export-ModuleMember -Function Convert-CentigradeToFahrenheit
Export-ModuleMember -Function Convert-FahrenheitToCentigrade
Export-ModuleMember -Alias c2f, f2c

Dieses Modul enthält zwei Funktionen, die jeweils einen Alias aufweisen. Standardmäßig werden alle Funktionsnamen und nur Funktionsnamen exportiert. Nachdem das Cmdlet Export-ModuleMember jedoch verwendet wurde, um etwas zu exportieren, werden nur die Dinge exportiert, die explizit ausgewählt wurden. Eine Reihe von Befehlen und Elementen kann in einem Aufruf oder einer Reihe von Aufrufen dieses Cmdlets exportiert werden. Solche Aufrufe sind für die aktuelle Sitzung kumulativ.

11.3 Installieren eines Skriptmoduls

Ein Skriptmodul wird in einer Skriptdatei definiert, und Module können in einem beliebigen Verzeichnis gespeichert werden. Die Umgebungsvariable PSModulePath verweist auf eine Reihe von Verzeichnissen, die durchsucht werden sollen, wenn modulbezogene Cmdlets nach Modulen suchen, deren Namen keinen vollqualifizierten Pfad enthalten. Zusätzliche Suchpfade können bereitgestellt werden, beispielsweise

$Env:PSModulePath = $Env:PSModulePath + ";<additional-path>"

Alle hinzugefügten zusätzlichen Pfade wirken sich nur auf die aktuelle Sitzung aus.

Alternativ kann ein vollqualifizierter Pfad angegeben werden, wenn ein Modul importiert wird.

11.4 Importieren eines Skriptmoduls

Bevor die Ressourcen in einem Modul verwendet werden können, muss dieses Modul mithilfe des Cmdlets Import-Modulein die aktuelle Sitzung importiert werden. Import-Module kann die Ressourcen, die es tatsächlich importiert, einschränken.

Wenn ein Modul importiert wird, wird die Skriptdatei ausgeführt. Dieser Prozess kann konfiguriert werden, indem ein oder mehrere Parameter in der Skriptdatei definiert und entsprechende Argumente über den ArgumentList-Parameter von Import-Moduleübergeben werden.

Betrachten Sie das folgende Skript, das diese Funktionen und Aliase verwendet, die in §11.2definiert sind:

Import-Module "E:\Scripts\Modules\PSTest_Temperature" -Verbose

"0 degrees C is " + (Convert-CentigradeToFahrenheit 0) + " degrees F"
"100 degrees C is " + (c2f 100) + " degrees F"
"32 degrees F is " + (Convert-FahrenheitToCentigrade 32) + " degrees C"
"212 degrees F is " + (f2c 212) + " degrees C"

Beim Importieren eines Moduls tritt ein Namenskonflikt auf, wenn Befehle oder Elemente im Modul dieselben Namen wie Befehle oder Elemente in der Sitzung aufweisen. Ein Namenskonflikt führt dazu, dass ein Name ausgeblendet oder ersetzt wird. Der Präfixparameter von Import-Module kann verwendet werden, um Namenskonflikte zu vermeiden. Außerdem können die Parameter Alias, Cmdlet, Functionund Variable die Auswahl der zu importierenden Befehle einschränken und dadurch die Wahrscheinlichkeit eines Namenskonflikts verringern.

Selbst wenn ein Befehl ausgeblendet ist, kann er durch die Qualifizierung seines Namens mit dem Namen des Moduls, aus dem er stammt, ausgeführt werden. Beispielsweise ruft & M\F 100 die Funktion F in Modul M auf und übergibt ihr das Argument 100.

Wenn die Sitzung Befehle derselben Art mit demselben Namen enthält, z. B. zwei Cmdlets mit demselben Namen, wird standardmäßig der zuletzt hinzugefügte Befehl ausgeführt.

Unter §3.5.6 finden Sie eine Erörterung im Zusammenhang mit Modulen.

11.5 Entfernen eines Skriptmoduls

Ein oder mehrere Module können über das Cmdlet Remove-Moduleaus einer Sitzung entfernt werden.

Durch das Entfernen eines Moduls wird das Modul nicht deinstalliert.

In einem Skriptmodul ist es möglich, Code anzugeben, der vor der Entfernung dieses Moduls ausgeführt werden soll, wie folgt:

$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { *on-removal-code* }

11.6 Modulmanifeste

Wie in §11.1angegeben, ist ein Manifestmodul eine Datei, die Informationen zu einem Modul enthält, und steuert bestimmte Aspekte der Verwendung dieses Moduls.

Ein Modul muss nicht über ein entsprechendes Manifest verfügen, aber wenn dies der Fall ist, hat dieses Manifest denselben Namen wie das beschriebene Modul, aber mit einer .psd1 Dateierweiterung.

Ein Manifest enthält eine begrenzte Teilmenge des PowerShell-Skripts, die eine Hashtable mit einer Reihe von Schlüsseln zurückgibt. Diese Schlüssel und ihre Werte geben die Manifestelemente für dieses Modul an. Das heißt, sie beschreiben den Inhalt und die Attribute des Moduls, definieren alle Voraussetzungen und bestimmen, wie die Komponenten verarbeitet werden.

Im Wesentlichen ist ein Manifest eine Datendatei; Sie kann jedoch Verweise auf Datentypen, die If-Anweisung und die arithmetischen und Vergleichsoperatoren enthalten. (Zuordnungen, Funktionsdefinitionen und Schleifen sind nicht zulässig.) Ein Manifest verfügt auch über Lesezugriff auf Umgebungsvariablen und kann Aufrufe des Cmdlets Join-Pathenthalten, sodass Pfade erstellt werden können.

Anmerkung

Editor-Hinweis: Das ursprüngliche Dokument enthält eine Liste der in einer Modulmanifestdatei zulässigen Schlüssel. Diese Liste ist veraltet und unvollständig. Eine vollständige Liste der Schlüssel in einem Modulmanifest finden Sie unter New-ModuleManifest.

Der einzige erforderliche Schlüssel ist ModuleVersion.

Hier ist ein Beispiel für ein einfaches Manifest:

@{
ModuleVersion = '1.0'
Author = 'John Doe'
RequiredModules = @()
FunctionsToExport = 'Set*','Get*','Process*'
}

Der Schlüssel GUID hat den Wert string. Sie gibt einen Globally Unique IDentifier (GUID) für das Modul an. Die GUID kann verwendet werden, um Module mit identischem Namen zu unterscheiden. Rufen Sie zum Erstellen einer neuen GUID die Methode [guid]::NewGuid()auf.

11.7 Dynamische Module

Ein dynamisches Modul ist ein Modul, das zur Laufzeit vom Cmdlet New-Moduleim Arbeitsspeicher erstellt wird; es wird nicht vom Datenträger geladen. Betrachten Sie das folgende Beispiel:

$sb = {
    function Convert-CentigradeToFahrenheit ([double]$tempC) {
        return ($tempC * (9.0 / 5.0)) + 32.0
    }

    New-Alias c2f Convert-CentigradeToFahrenheit

    function Convert-FahrenheitToCentigrade ([double]$tempF) {
        return ($tempF - 32.0) * (5.0 / 9.0)
    }

    New-Alias f2c Convert-FahrenheitToCentigrade

    Export-ModuleMember -Function Convert-CentigradeToFahrenheit
    Export-ModuleMember -Function Convert-FahrenheitToCentigrade
    Export-ModuleMember -Alias c2f, f2c
}

New-Module -Name MyDynMod -ScriptBlock $sb
Convert-CentigradeToFahrenheit 100
c2f 100

Der Skriptblock $sb definiert den Inhalt des Moduls, in diesem Fall zwei Funktionen und zwei Aliase für diese Funktionen. Wie bei einem Modul auf dem Datenträger werden nur Funktionen standardmäßig exportiert, sodass Export-ModuleMember Cmdlets Aufrufe vorhanden sind, um sowohl die Funktionen als auch die Aliase zu exportieren.

Sobald New-Module ausgeführt wird, stehen die vier exportierten Namen für die Verwendung in der Sitzung zur Verfügung, wie die Aufrufe von Convert-CentigradeToFahrenheit und c2f zeigen.

Wie bei allen Modulen werden die Elemente von dynamischen Modulen in einem privaten Modulbereich ausgeführt, der ein untergeordnetes Element des globalen Bereichs ist. Get-Module kann kein dynamisches Modul abrufen, aber Get-Command kann die exportierten Mitglieder abrufen.

Um ein dynamisches Modul für Get-Module verfügbar zu machen, reichen Sie einen New-Module-Befehl an Import-Module weiter, oder reichen Sie das Modulobjekt, das New-Module zurückgibt, an Import-Module weiter. Durch diese Aktion wird das dynamische Modul der Get-Module-Liste hinzugefügt, aber das Modul wird nicht auf dem Datenträger gespeichert oder persistent gemacht.

11.8 Schließungen

Mit einem dynamischen Modul kann eine Schließung erstellt werden, eine Funktion mit angefügten Daten. Betrachten Sie das folgende Beispiel:

function Get-NextID ([int]$StartValue = 1) {
    $nextID = $StartValue
    {
        ($Script:nextID++)
    }.GetNewClosure()
}

$v1 = Get-NextID      # get a scriptblock with $StartValue of 0
& $v1                 # invoke Get-NextID getting back 1
& $v1                 # invoke Get-NextID getting back 2

$v2 = Get-NextID 100  # get a scriptblock with $StartValue of 100
& $v2                 # invoke Get-NextID getting back 100
& $v2                 # invoke Get-NextID getting back 101

Der Zweck besteht darin, dass Get-NextID die nächste ID einer Sequenz zurückgibt, deren Startwert spezifiziert werden kann. Es müssen jedoch mehrere Sequenzen unterstützt werden, die jeweils einen eigenen $StartValue und einen eigenen $nextID-Kontext haben. Dies wird durch den Aufruf der Methode [scriptblock]::GetNewClosure (§4.3.7) erreicht.

Jedes Mal, wenn eine neue Schließung von GetNewClosure erstellt wird, wird ein neues dynamisches Modul erstellt, und die Variablen im Bereich des Aufrufers (in diesem Fall der Skriptblock, der das Inkrement enthält) werden in dieses neue Modul kopiert. Um sicherzustellen, dass die nextId innerhalb der übergeordneten Funktion (aber außerhalb des Skriptblocks) erhöht wird, ist das explizite Skript: Bereichspräfix erforderlich.

Natürlich muss der Skriptblock keine benannte Funktion sein; Zum Beispiel:

$v3 = & {      # get a scriptblock with $StartValue of 200
    param ([int]$StartValue = 1)
    $nextID = $StartValue
    {
        ($Script:nextID++)
    }.GetNewClosure()
} 200

& $v3          # invoke script getting back 200
& $v3          # invoke script getting back 201