Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Se ci si trova a usare spesso gli stessi script o one-liner di PowerShell, trasformarli in strumenti riutilizzabili è ancora più importante. La creazione di pacchetti delle funzioni in un modulo script offre un aspetto più professionale e li rende più facili da supportare e condividere con altri utenti.
Funzioni di dot-sourcing
Una cosa che non abbiamo illustrato nel capitolo precedente è le funzioni dot-sourcing. Quando si definisce una funzione in uno script ma che non fa parte di un modulo, l'unico modo per caricarla in memoria è eseguendo il dot-sourcing del file .ps1.
Ad esempio, salvare la funzione seguente in un file denominato Get-MrPSVersion.ps1.
function Get-MrPSVersion {
$PSVersionTable
}
Quando si esegue lo script, sembra che non accada nulla.
.\Get-MrPSVersion.ps1
Il tentativo di chiamare la funzione genera un errore perché non viene caricato in memoria.
Get-MrPSVersion
Get-MrPSVersion : The term 'Get-MrPSVersion' is not recognized as the name
of a cmdlet, function, script file, or operable program. Check the spelling
of the name, or if a path was included, verify that the path is correct and
try again.
At line:1 char:1
+ Get-MrPSVersion
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-MrPSVersion:String) [],
CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
È possibile verificare se le funzioni vengono caricate in memoria verificandone l'esistenza nella funzione: PSDrive.
Get-ChildItem -Path Function:\Get-MrPSVersion
Get-ChildItem : Cannot find path 'Get-MrPSVersion' because it does not
exist.
At line:1 char:1
+ Get-ChildItem -Path Function:\Get-MrPSVersion
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-MrPSVersion:String) [Get
-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.Ge
tChildItemCommand
Il problema relativo all'esecuzione dello script che definisce la funzione è che lo carica nell'ambito dello script . Al termine dell'esecuzione dello script, PowerShell rimuove tale ambito insieme alla funzione.
Per mantenere disponibile la funzione dopo l'esecuzione dello script, è necessario caricarla nell'ambito globale . Puoi ottenere questo risultato eseguendo il dot-sourcing del file di script. A questo scopo, è possibile usare un percorso relativo.
. .\Get-MrPSVersion.ps1
È anche possibile utilizzare il percorso completo dello script quando si esegue il dot-sourcing.
. C:\Demo\Get-MrPSVersion.ps1
Se parte del percorso viene archiviata in una variabile, è possibile combinarla con il resto del percorso. Non è necessario usare la concatenazione di stringhe per eseguire questa operazione.
$Path = 'C:\'
. $Path\Get-MrPSVersion.ps1
Ora, se si controlla la funzione PSDrive, si noterà che la Get-MrPSVersion funzione è disponibile.
Get-ChildItem -Path Function:\Get-MrPSVersion
CommandType Name Version
----------- ---- -------
Function Get-MrPSVersion
Moduli di script
In PowerShell un modulo script è semplicemente un .psm1 file che contiene una o più funzioni, proprio come uno script normale, ma con un'estensione di file diversa.
Come si crea un modulo di script? È possibile presupporre qualcosa con un comando denominato simile a New-Module. Questo presupposto è un'ipotesi ragionevole, ma tale comando crea effettivamente un modulo dinamico, non un modulo di script.
Questo scenario è un buon promemoria per leggere sempre la documentazione di aiuto, anche quando un nome di comando è esattamente come quello necessario.
help New-Module
NAME
New-Module
SYNOPSIS
Creates a new dynamic module that exists only in memory.
SYNTAX
New-Module [-Name] <System.String> [-ScriptBlock]
<System.Management.Automation.ScriptBlock> [-ArgumentList
<System.Object[]>] [-AsCustomObject] [-Cmdlet <System.String[]>]
[-Function <System.String[]>] [-ReturnResult] [<CommonParameters>]
DESCRIPTION
The `New-Module` cmdlet creates a dynamic module from a script block.
The members of the dynamic module, such as functions and variables, are
immediately available in the session and remain available until you
close the session.
Like static modules, by default, the cmdlets and functions in a dynamic
module are exported and the variables and aliases are not. However, you
can use the Export-ModuleMember cmdlet and the parameters of
`New-Module` to override the defaults.
You can also use the **AsCustomObject** parameter of `New-Module` to return
the dynamic module as a custom object. The members of the modules, such
as functions, are implemented as script methods of the custom object
instead of being imported into the session.
Dynamic modules exist only in memory, not on disk. Like all modules,
the members of dynamic modules run in a private module scope that is a
child of the global scope. Get-Module cannot get a dynamic module, but
Get-Command can get the exported members.
To make a dynamic module available to `Get-Module`, pipe a `New-Module`
command to Import-Module, or pipe the module object that `New-Module`
returns to `Import-Module`. This action adds the dynamic module to the
`Get-Module` list, but it does not save the module to disk or make it
persistent.
RELATED LINKS
Online Version: https://learn.microsoft.com/powershell/module/microsoft.
powershell.core/new-module?view=powershell-5.1&WT.mc_id=ps-gethelp
Export-ModuleMember
Get-Module
Import-Module
Remove-Module
about_Modules
REMARKS
To see the examples, type: "Get-Help New-Module -Examples".
For more information, type: "Get-Help New-Module -Detailed".
For technical information, type: "Get-Help New-Module -Full".
For online help, type: "Get-Help New-Module -Online"
Il capitolo precedente ha indicato che le funzioni devono usare verbi approvati. In caso contrario, PowerShell genera un avviso quando il modulo viene importato.
Nell'esempio seguente viene usato il New-Module cmdlet per creare un modulo dinamico in memoria, in particolare per illustrare cosa accade quando non si usa un verbo approvato.
New-Module -Name MyModule -ScriptBlock {
function Return-MrOsVersion {
Get-CimInstance -ClassName Win32_OperatingSystem |
Select-Object -Property @{Label='OperatingSystem';Expression={$_.Caption}}
}
Export-ModuleMember -Function Return-MrOsVersion
} | Import-Module
WARNING: The names of some imported commands from the module 'MyModule' include
unapproved verbs that might make them less discoverable. To find the commands with
unapproved verbs, run the Import-Module command again with the Verbose parameter. For a
list of approved verbs, type Get-Verb.
Anche se è stato usato il New-Module cmdlet nell'esempio precedente, come indicato in precedenza, non è il comando per la creazione di moduli di script in PowerShell.
Per creare un modulo script, salvare le funzioni in un .psm1 file. Ad esempio, salvare le due funzioni seguenti in un file denominato MyScriptModule.psm1.
function Get-MrPSVersion {
$PSVersionTable
}
function Get-MrComputerName {
$env:COMPUTERNAME
}
Provare a eseguire una delle funzioni.
Get-MrComputerName
Quando si chiama la funzione, viene visualizzato un errore che indica che PowerShell non riesce a trovarlo. Come in precedenza, il controllo della Funzione: PSDrive conferma che non è caricato in memoria.
Get-MrComputerName : The term 'Get-MrComputerName' is not recognized as the
name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is
correct and try again.
At line:1 char:1
+ Get-MrComputerName
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-MrComputerName:String) [
], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Per rendere disponibile la funzione, è possibile importare manualmente il MyScriptModule.psm1 file usando il Import-Module cmdlet .
Import-Module C:\MyScriptModule.psm1
PowerShell ha introdotto il caricamento automatico dei moduli nella versione 3. Per sfruttare questa funzionalità, il modulo script deve essere salvato in una cartella con lo stesso nome di base del .psm1 file. Tale cartella deve trovarsi in una delle directory specificate nella $env:PSModulePath variabile di ambiente.
$env:PSModulePath
L'output di $env:PSModulePath è difficile da leggere.
C:\Users\mike-ladm\Documents\WindowsPowerShell\Modules;C:\Program Files\Wind
owsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules;C:\
Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\
Per rendere i risultati più leggibili, dividere i percorsi nel separatore di percorso punto e virgola in modo che ognuno venga visualizzato sulla propria riga.
$env:PSModulePath -split ';'
I primi tre percorsi nell'elenco sono i percorsi predefiniti del modulo. SQL Server Management Studio ha aggiunto l'ultimo percorso al momento dell'installazione.
C:\Users\mike-ladm\Documents\WindowsPowerShell\Modules
C:\Program Files\WindowsPowerShell\Modules
C:\Windows\system32\WindowsPowerShell\v1.0\Modules
C:\Program Files (x86)\Microsoft SQL Server\130\Tools\PowerShell\Modules\
Per il funzionamento del caricamento automatico del modulo, è necessario inserire il MyScriptModule.psm1 file in una cartella denominata MyScriptModulee tale cartella deve risiedere direttamente all'interno di uno dei percorsi elencati in
$env:PSModulePath.
Non tutti questi percorsi sono ugualmente utili. Ad esempio, il percorso utente corrente nel sistema non è il primo nell'elenco. Questo perché si accede a Windows con un account diverso da quello usato per eseguire PowerShell. Non punta quindi alla cartella documenti dell'utente.
Il secondo percorso è il percorso AllUsers , in cui vengono archiviati tutti i moduli.
Il terzo percorso punta a C:\Windows\System32, un percorso di sistema protetto. Solo Microsoft deve posizionare i moduli, perché rientra nella struttura di directory del sistema operativo.
Dopo aver inserito il .psm1 file in una cartella appropriata all'interno di uno di questi percorsi, PowerShell carica automaticamente il modulo la prima volta che si chiama uno dei relativi comandi.
Manifesti del modulo
Ogni modulo deve includere un manifesto del modulo, ovvero un .psd1 file contenente i metadati relativi al modulo. Mentre l'estensione .psd1 viene usata per i manifesti, non tutti i .psd1 file sono manifesti del modulo. È anche possibile usarli per altri scopi, ad esempio la definizione dei dati dell'ambiente in un dsc
configurazione.
È possibile creare un manifesto del modulo usando il New-ModuleManifest cmdlet . L'unico parametro obbligatorio è Path, ma per il corretto funzionamento del modulo, è necessario specificare anche il parametro RootModule .
È consigliabile includere valori come Autore e Descrizione, soprattutto se si prevede di pubblicare il modulo in un repository NuGet usando PowerShellGet. Questi campi sono obbligatori in questo scenario.
Un modo rapido per stabilire se un modulo non dispone di un manifesto consiste nel controllare la versione.
Get-Module -Name MyScriptModule
Un numero di versione di 0.0 è un segno chiaro che il modulo non dispone di un manifesto.
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 0.0 MyScriptModule {Get-MrComputer...
È consigliabile includere tutti i dettagli consigliati durante la creazione di un manifesto del modulo per assicurarsi che il modulo sia ben documentato e pronto per la condivisione o la pubblicazione.
$moduleManifestParams = @{
Path = "$env:ProgramFiles\WindowsPowerShell\Modules\MyScriptModule\MyScriptModule.psd1"
RootModule = 'MyScriptModule'
Author = 'Mike F. Robbins'
Description = 'MyScriptModule'
CompanyName = 'mikefrobbins.com'
}
New-ModuleManifest @moduleManifestParams
Se si omettono valori durante la creazione iniziale del manifesto del modulo, è possibile aggiungerlo o aggiornarlo in un secondo momento usando il Update-ModuleManifest cmdlet . Evitare di ricreare il manifesto con New-ModuleManifest una volta che lo hai creato, poiché ciò genera un nuovo GUID.
Definizione di funzioni pubbliche e private
In alcuni casi, il modulo potrebbe includere funzioni helper che non si desidera esporre agli utenti. Queste funzioni private vengono usate internamente da altre funzioni nel modulo, ma non vengono esposte agli utenti. Esistono alcuni modi per gestire questo scenario.
Se non si seguono le procedure consigliate e si dispone solo di un .psm1 file senza un manifesto del modulo, l'unica opzione consiste nel controllare la visibilità usando il Export-ModuleMember cmdlet . Questa opzione consente di definire in modo esplicito quali funzioni devono essere esposte direttamente dall'interno del file del .psm1 modulo di script, mantenendo tutto il resto privato per impostazione predefinita.
Nell'esempio seguente, solo la Get-MrPSVersion funzione viene esposta agli utenti del modulo, mentre la Get-MrComputerName funzione rimane accessibile internamente ad altre funzioni all'interno del modulo.
function Get-MrPSVersion {
$PSVersionTable
}
function Get-MrComputerName {
$env:COMPUTERNAME
}
Export-ModuleMember -Function Get-MrPSVersion
Determinare quali comandi sono disponibili pubblicamente nel modulo MyScriptModule .
Get-Command -Module MyScriptModule
CommandType Name Version
----------- ---- -------
Function Get-MrPSVersion 1.0
Se si aggiunge un manifesto del modulo al modulo, è consigliabile elencare in modo esplicito le funzioni da esportare nella sezione FunctionsToExport . Questa opzione consente di controllare gli elementi esposti agli utenti dal file manifesto del .psd1 modulo.
FunctionsToExport = 'Get-MrPSVersion'
Non è necessario usare sia Export-ModuleMember nel .psm1 file che nella FunctionsToExport sezione del manifesto del modulo. Entrambi gli approcci sono sufficienti da soli.
Sommario
In questo capitolo si è appreso come trasformare le funzioni in un modulo script in PowerShell. Sono state inoltre esaminate le procedure consigliate per la creazione di moduli di script, inclusa l'importanza di aggiungere un manifesto del modulo per definire i metadati e gestire i comandi esportati.
Recensione
- Come si crea un modulo di script in PowerShell?
- Perché è importante usare verbi approvati per i nomi delle funzioni?
- Come si crea un manifesto del modulo in PowerShell?
- Quali sono i due modi per esportare solo funzioni specifiche da un modulo?
- Quali condizioni devono essere soddisfatte per il caricamento automatico di un modulo quando si esegue uno dei relativi comandi?