11. Modules

Inleiding tot 11.1

Zoals vermeld in :3.14 is een module een zelfstandige, herbruikbare eenheid waarmee PowerShell-code kan worden gepartitief, geordend en geabstraheerd. Een module kan een of meer moduleleden bevatten. Dit zijn opdrachten (zoals cmdlets en functies) en items (zoals variabelen en aliassen). De namen van deze leden kunnen privé worden gehouden in de module of worden geëxporteerd naar de sessie waarin de module wordt geïmporteerd.

Er zijn drie verschillende moduletypen: manifest, script en binair. Een manifestmodule is een bestand dat informatie bevat over een module en die bepaalde aspecten van het gebruik van die module beheert. Een scriptmodule is een PowerShell-scriptbestand met de bestandsextensie van in .psm1 plaats van .ps1. Een binaire module bevat klassetypen die cmdlets en providers definiëren. In tegenstelling tot scriptmodules worden binaire modules geschreven in gecompileerde talen. Binaire modules vallen niet onder deze specificatie.

Een binaire module is een .NET-assembly (d.v.t. een DLL) die is gecompileerd voor de PowerShell-bibliotheken.

Modules kunnen worden genest; Dat wil zeggen dat de ene module een andere module kan importeren. Een module die aan geneste modules is gekoppeld, is een hoofdmodule.

Wanneer een PowerShell-sessie wordt gemaakt, worden standaard geen modules geïmporteerd.

Wanneer modules worden geïmporteerd, wordt het zoekpad dat wordt gebruikt om ze te vinden, gedefinieerd door de omgevingsvariabele PSModulePath.

De volgende cmdlets hebben te maken met modules:

11.2 Een scriptmodule schrijven

Een scriptmodule is een scriptbestand. Kijk eens naar de volgende scriptmodule:

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

Deze module bevat twee functies, die elk een alias hebben. Standaard worden alle functienamen en alleen functienamen geëxporteerd. Zodra de cmdlet echter is gebruikt om Export-ModuleMember iets te exporteren, worden alleen de dingen geëxporteerd die expliciet worden geëxporteerd. Een reeks opdrachten en items kan worden geëxporteerd in één aanroep of een aantal aanroepen naar deze cmdlet; dergelijke aanroepen zijn cumulatief voor de huidige sessie.

11.3 Een scriptmodule installeren

Een scriptmodule wordt gedefinieerd in een scriptbestand en modules kunnen worden opgeslagen in elke map. De omgevingsvariabele PSModulePath wijst naar een set van te doorzoeken directories wanneer module-gerelateerde cmdlets zoeken naar modules waarvan de namen geen volledig gekwalificeerde pad bevatten. Er kunnen aanvullende opzoekpaden worden opgegeven; bijvoorbeeld

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

Eventuele extra paden die worden toegevoegd, zijn alleen van invloed op de huidige sessie.

U kunt ook een volledig gekwalificeerd pad opgegeven wanneer een module wordt geïmporteerd.

11.4 Een scriptmodule importeren

Voordat de resources in een module kunnen worden gebruikt, moet die module worden geïmporteerd in de huidige sessie met behulp van de cmdlet Import-Module. Import-Module kan de resources beperken die daadwerkelijk worden geïmporteerd.

Wanneer een module wordt geïmporteerd, wordt het scriptbestand uitgevoerd. Dit proces kan worden geconfigureerd door een of meer parameters in het scriptbestand te definiëren en bijbehorende argumenten door te geven via de parameter ArgumentList van Import-Module.

Kijk eens naar het volgende script dat gebruikmaakt van deze functies en aliassen die zijn gedefinieerd in :11.2:

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

"0 degrees C is &quot; + (Convert-CentigradeToFahrenheit 0) + &quot; 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"

Het importeren van een module veroorzaakt een naamconflict wanneer opdrachten of items in de module dezelfde namen hebben als opdrachten of items in de sessie. Een naamconflict resulteert in een naam die wordt verborgen of vervangen. De parameter Prefix van kan Import-Module worden gebruikt om naamconflicten te voorkomen. Bovendien kunnen de parameters Alias, Cmdlet, Function en Variable de selectie van te importeren opdrachten beperken, waardoor de kans op naamconflicten wordt verkleind.

Zelfs als een opdracht verborgen is, kan deze worden uitgevoerd door de naam ervan te kwalificeren met de naam van de module waaruit deze afkomstig is. Roept bijvoorbeeld de & M\F 100 functie F aan in module M en geeft het argument 100 door.

Wanneer de sessie opdrachten van hetzelfde type met dezelfde naam bevat, zoals twee cmdlets met dezelfde naam, wordt standaard de meest recent toegevoegde opdracht uitgevoerd.

Zie :3.5.6 voor een bespreking van het bereik met betrekking tot modules.

11.5 Een scriptmodule verwijderen

Een of meer modules kunnen worden verwijderd uit een sessie via de cmdlet Remove-Module.

Als u een module verwijdert, wordt de module niet verwijderd.

In een scriptmodule kunt u als volgt code opgeven die moet worden uitgevoerd voordat deze module wordt verwijderd:

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

11.6 Modulemanifests

Zoals vermeld in :11.1 is een manifestmodule een bestand dat informatie over een module bevat en bepaalde aspecten van het gebruik van die module beheert.

Een module hoeft geen bijbehorend manifest te hebben, maar als dat het doet, heeft dat manifest dezelfde naam als de module die wordt beschreven, maar met een bestandsextensie .psd1 .

Een manifest bevat een beperkte subset van een PowerShell-script, die een hashtabel met een set sleutels retourneert. Deze sleutels en hun waarden geven de manifestelementen voor die module op. Dat wil zeggen dat ze de inhoud en kenmerken van de module beschrijven, eventuele vereisten definiëren en bepalen hoe de onderdelen worden verwerkt.

In wezen is een manifest een gegevensbestand; Het kan echter verwijzingen bevatten naar gegevenstypen, de if-instructie en de rekenkundige en vergelijkingsoperators. (Toewijzingen, functiedefinities en lussen zijn niet toegestaan.) Een manifest heeft ook leestoegang tot omgevingsvariabelen en kan aanroepen naar de cmdlet Join-Pathbevatten, zodat paden kunnen worden samengesteld.

Notitie

Opmerking van de editor: Het oorspronkelijke document bevat een lijst met sleutels die zijn toegestaan in een modulemanifestbestand. Deze lijst is verouderd en onvolledig. Zie New-ModuleManifest voor een volledige lijst met sleutels in een modulemanifest.

De enige sleutel die vereist is, is ModuleVersion.

Hier is een voorbeeld van een eenvoudig manifest:

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

De sleutel-GUID heeft een string waarde. Hiermee geeft u een Globally Unique IDentifier (GUID) op voor de module. De GUID kan worden gebruikt om onderscheid te maken tussen modules met dezelfde naam. Als u een nieuwe GUID wilt maken, roept u de methode aan [guid]::NewGuid().

11.7 Dynamische modules

Een dynamische module is een module die tijdens runtime in het geheugen wordt gemaakt door de cmdlet New-Module. Deze wordt niet van schijf geladen. Kijk eens naar het volgende voorbeeld:

$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

Het scriptblok $sb definieert de inhoud van de module, in dit geval twee functies en twee aliassen voor deze functies. Net als bij een module op schijf worden standaard alleen functies geëxporteerd. Export-ModuleMember Daarom bestaan er cmdlets-aanroepen om zowel de functies als de aliassen te exporteren.

Zodra New-Module wordt uitgevoerd, zijn de vier geëxporteerde namen beschikbaar voor gebruik in de sessie, zoals wordt weergegeven door de aanroepen naar de Convert-CentigradeToFahrenheit en c2f.

Net als alle modules worden de leden van dynamische modules uitgevoerd in een privémodulebereik dat een onderliggend punt van het globale bereik is. Get-Module kan geen dynamische module krijgen, maar kan Get-Command de geëxporteerde leden wel op halen.

Als u een dynamische module beschikbaar wilt maken voor Get-Module, geeft u een New-Module opdracht door aan Import-Moduleof s pipet u het moduleobject New-Module dat retourneert door naar Import-Module. Met deze actie wordt de dynamische module toegevoegd aan de Get-Module lijst, maar wordt de module niet op schijf opgeslagen of persistent.

11.8 Sluitingen

Een dynamische module kan worden gebruikt om een sluiting te maken, een functie met gekoppelde gegevens. Kijk eens naar het volgende voorbeeld:

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 1

$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

De intentie hier is dat de Get-NextID volgende id in een reeks retourneert waarvan de beginwaarde kan worden opgegeven. Er moeten echter meerdere reeksen worden ondersteund, elk met een eigen context $startValue en $nextID . Dit wordt bereikt door de aanroep van de methode [scriptblock]::GetNewClosure (4.3.7).

GetNewClosureTelkens als een nieuwe sluiting wordt gemaakt door , wordt er een nieuwe dynamische module gemaakt en worden de variabelen in het bereik van de aanroeper (in dit geval het scriptblok met de toename) gekopieerd naar deze nieuwe module. Om ervoor te zorgen dat de nextId die is gedefinieerd in de bovenliggende functie (maar buiten het scriptblok) wordt verhoogd, is het expliciete script: bereik voorvoegsel nodig.

Het scriptblok hoeft natuurlijk geen benoemde functie te zijn; bijvoorbeeld:

$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