Udostępnij za pośrednictwem


11. Moduły

Notatka redakcyjna

Ważny

Specyfikacja języka Windows PowerShell 3.0 została opublikowana w grudniu 2012 r. i jest oparta na Windows PowerShell 3.0. Ta specyfikacja nie odzwierciedla bieżącego stanu programu PowerShell. Nie ma planu aktualizacji tej dokumentacji w celu odzwierciedlenia bieżącego stanu. Ta dokumentacja jest przedstawiona tutaj w celu uzyskania informacji historycznych.

Dokument specyfikacji jest dostępny jako dokument programu Microsoft Word z Centrum pobierania Microsoft pod adresem: https://www.microsoft.com/download/details.aspx?id=36389 Dokument programu Word został przekonwertowany na prezentację tutaj w witrynie Microsoft Learn. Podczas konwersji wprowadzono pewne zmiany redakcyjne w celu dostosowania formatowania dla platformy Docs. Usunięto niektóre literówki i drobne błędy.

11.1 Wprowadzenie

Zgodnie z §3.14moduł jest samodzielną jednostką wielokrotnego użytku, która umożliwia partycjonowanie, organizowanie i abstrakcję kodu programu PowerShell. Moduł może zawierać jeden lub więcej członków modułu, które są poleceniami (takimi jak polecenia cmdlet i funkcje) oraz elementami (takimi jak zmienne i aliasy). Nazwy tych elementów członkowskich mogą być przechowywane prywatnie w module lub mogą być wyeksportowane do sesji, w której moduł jest zaimportowany.

Istnieją trzy różne typy modułów : manifest, skrypt i binarne. Moduł manifestu to plik zawierający informacje o module i kontroluje niektóre aspekty użycia tego modułu. Moduł skryptu to plik skryptu programu PowerShell z rozszerzeniem pliku .psm1 zamiast .ps1. Moduł binarny zawiera typy klas, które definiują cmdlety i dostawców. W przeciwieństwie do modułów skryptów moduły binarne są zapisywane w skompilowanych językach. Moduły binarne nie są objęte tą specyfikacją.

Moduł binarny to zestaw .NET (tj. biblioteka DLL), który został skompilowany względem bibliotek programu PowerShell.

Moduły mogą zagnieżdżać; co oznacza, że jeden moduł może importować inny moduł. Moduł, który ma skojarzone moduły zagnieżdżone, jest modułem głównym .

Po utworzeniu sesji programu PowerShell domyślnie nie są importowane żadne moduły.

Po zaimportowaniu modułów ścieżka wyszukiwania używana do ich zlokalizowania jest definiowana przez zmienną środowiskową PSModulePath.

Następujące polecenia cmdlet dotyczą modułów:

  • Get-Module: Rozpoznaje moduły, które zostały zaimportowane lub można zaimportować.
  • import-module: dodaje co najmniej jeden moduł do bieżącej sesji (zobacz §11.4)
  • Export-ModuleMember: identyfikuje elementy członkowskie modułu, które mają zostać wyeksportowane
  • Remove-Module : usuwa jeden lub więcej modułów z bieżącej sesji (zobacz §11.5)
  • New-Module : Tworzy moduł dynamiczny (zobacz §11.7)

11.2 Pisanie modułu skryptu

Moduł skryptu to plik skryptu. Rozważmy następujący moduł skryptu:

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

Ten moduł zawiera dwie funkcje, z których każdy ma alias. Domyślnie wszystkie nazwy funkcji i tylko nazwy funkcji są eksportowane. Jednak gdy polecenie cmdlet Export-ModuleMember zostało użyte do wyeksportowania czegokolwiek, zostaną wyeksportowane tylko te elementy, które zostały wyeksportowane jawnie. Serię poleceń i elementów można wyeksportować w jednym wywołaniu lub w wielu wywołaniach tego polecenia cmdlet; takie wywołania są skumulowane dla bieżącej sesji.

11.3 Instalowanie modułu skryptu

Moduł skryptu jest zdefiniowany w pliku skryptu, a moduły mogą być przechowywane w dowolnym katalogu. Zmienna środowiskowa PSModulePath wskazuje zestaw katalogów, które mają być przeszukiwane, gdy polecenia cmdlet związane z modułami wyszukują moduły, których nazwy nie zawierają w pełni kwalifikowanej ścieżki. Można podać dodatkowe ścieżki wyszukiwania; na przykład

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

Wszystkie dodane dodatkowe ścieżki mają wpływ tylko na bieżącą sesję.

Alternatywnie można określić w pełni kwalifikowaną ścieżkę podczas importowania modułu.

11.4 Importowanie modułu skryptu

Aby można było użyć zasobów w module, ten moduł musi zostać zaimportowany do bieżącej sesji przy użyciu polecenia cmdlet Import-Module. Import-Module może ograniczyć zasoby, które faktycznie importuje.

Po zaimportowaniu modułu jest wykonywany jego plik skryptu. Ten proces można skonfigurować przez zdefiniowanie co najmniej jednego parametru w pliku skryptu i przekazanie odpowiednich argumentów za pomocą parametru ArgumentList Import-Module.

Rozważ następujący skrypt, który używa tych funkcji i aliasów zdefiniowanych w §11.2:

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"

Importowanie modułu powoduje konflikt nazw, gdy polecenia lub elementy w module mają takie same nazwy jak polecenia lub elementy w sesji. Konflikt nazw powoduje ukrycie lub zastąpienie nazwy. Parametr prefiksu Import-Module może służyć do uniknięcia konfliktów nazewnictwa. Ponadto alias , cmdlet , funkcja oraz parametry zmiennej ,,,i mogą ograniczyć wybór poleceń do zaimportowania, zmniejszając w ten sposób prawdopodobieństwo konfliktu nazw.

Nawet jeśli polecenie jest ukryte, można go uruchomić, kwalifikując jego nazwę z nazwą modułu, w którym pochodzi. Na przykład & M\F 100 wywołuje funkcję F w module Mi przekazuje argument 100.

Gdy sesja zawiera polecenia tego samego rodzaju o tej samej nazwie, takie jak dwa polecenia cmdlet o tej samej nazwie, domyślnie uruchamia ostatnio dodane polecenie.

Zobacz §3.5.6, aby zapoznać się z omówieniem zakresu w odniesieniu do modułów.

11.5 Usuwanie modułu skryptu

Co najmniej jeden moduł można usunąć z sesji za pomocą polecenia cmdlet Remove-Module.

Usunięcie modułu nie powoduje odinstalowania modułu.

W module skryptu można określić kod, który ma zostać wykonany przed usunięciem tego modułu w następujący sposób:

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

Manifesty modułu 11.6

Zgodnie z §11.1moduł manifestu jest plikiem zawierającym informacje o module i kontroluje niektóre aspekty użycia tego modułu.

Moduł nie musi mieć odpowiedniego manifestu, ale jeśli tak, ten manifest ma taką samą nazwę jak opis modułu, ale z rozszerzeniem .psd1 pliku.

Manifest zawiera ograniczony podzbiór skryptu programu PowerShell, który zwraca tabelę skrótu zawierającą zestaw kluczy. Te klucze i ich wartości określają elementy manifestu dla tego modułu. Oznacza to, że opisują zawartość i atrybuty modułu, definiują wszelkie wymagania wstępne i określają sposób przetwarzania składników.

Zasadniczo manifest jest plikiem danych; może jednak zawierać odwołania do typów danych, instrukcji if oraz operatorów arytmetycznych i porównawczych. (Przypisania, definicje funkcji i pętle nie są dozwolone). Manifest ma również dostęp do odczytu do zmiennych środowiskowych i może zawierać wywołania polecenia cmdlet Join-Path, dzięki czemu można tworzyć ścieżki.

Notatka

Uwaga edytora: oryginalny dokument zawiera listę kluczy dozwolonych w pliku manifestu modułu. Ta lista jest nieaktualna i niekompletna. Aby uzyskać pełną listę kluczy w manifeście modułu, zobacz New-ModuleManifest.

Jedynym wymaganym kluczem jest ModuleVersion.

Oto przykład prostego manifestu:

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

Klucz , identyfikator GUID, ma wartość string. Określa globalnie unikatowy identyfikator (GUID) dla modułu. Identyfikator GUID można użyć do rozróżnienia modułów o tej samej nazwie. Aby utworzyć nowy identyfikator GUID, wywołaj metodę [guid]::NewGuid().

11.7 Moduły dynamiczne

Moduł dynamiczny to moduł, który jest tworzony w pamięci w czasie wykonywania przez polecenie cmdlet New-Module; nie jest ładowany z dysku. Rozważmy następujący przykład:

$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

Blok skryptu $sb definiuje zawartość modułu, w tym przypadku dwie funkcje i dwa aliasy do tych funkcji. Podobnie jak w przypadku modułu na dysku, tylko funkcje są domyślnie eksportowane, więc Export-ModuleMember wywołania poleceń cmdlet istnieją w celu wyeksportowania zarówno funkcji, jak i aliasów.

Po uruchomieniu New-Module cztery wyeksportowane nazwy są dostępne do użycia w sesji, jak pokazano przez wywołania Convert-CentigradeToFahrenheit i c2f.

Podobnie jak wszystkie moduły, elementy modułów dynamicznych działają w prywatnym zakresie modułu, który jest podrzędny względem zakresu globalnego. Get-Module nie może zdobyć modułu dynamicznego, ale Get-Command może uzyskać wyeksportowane członki.

Aby udostępnić moduł dynamiczny Get-Module, należy przekazać polecenie New-Module do Import-Modulelub przekazać obiekt modułu zwracany przez New-Module do Import-Module. Ta akcja dodaje moduł dynamiczny do listy Get-Module, ale nie zapisuje modułu na dysku ani nie powoduje jego trwałości.

11.8 Zamknięcia

Moduł dynamiczny może służyć do tworzenia zamknięcia, funkcji z dołączonymi danymi. Rozważmy następujący przykład:

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

Zamierzeniem jest, aby Get-NextID zwróciło następny identyfikator w sekwencji, której wartość początkową można określić. Jednak wiele sekwencji musi być obsługiwanych, przy czym każda z nich ma własny kontekst $startValue i $nextID. Jest to osiągane przez wywołanie metody [scriptblock]::GetNewClosure (§4.3.7).

Za każdym razem, gdy zostanie utworzone nowe zamknięcie przez GetNewClosure, zostanie utworzony nowy moduł dynamiczny, a zmienne w zakresie obiektu wywołującego (w tym przypadku blok skryptu zawierający przyrost) są kopiowane do tego nowego modułu. Aby upewnić się, że następny identyfikator zdefiniowany wewnątrz funkcji nadrzędnej (ale poza blokiem skryptu) jest zwiększany, wymagany jest jawny skrypt: prefiks zakresu.

Oczywiście blok skryptu nie musi być nazwaną funkcją; na przykład:

$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