Nell’ambito del rilascio di PowerShell Universal v5, stiamo aggiungendo alcune regole PSScriptAnalyzer personalizzate alla piattaforma per individuare più facilmente i problemi durante la creazione degli script. In questo articolo vedremo come creare regole PSScriptAnalyzer personalizzate.
PSScriptAnalyzer
PSScriptAnalyzer è uno strumento di analisi statica del codice per gli script PowerShell. Controlla la qualità del codice in base a un insieme di regole. Le regole integrate verificano ogni tipo di aspetto, come l’uso degli alias, gli spazi a fine riga, i controlli $null e altro ancora. Negli editor come VS Code, PSScriptAnalyzer viene eseguito in background per fornire un feedback in tempo reale sui propri script.
Internamente, l’estensione PowerShell esegue Invoke-ScriptAnalyzer per fornire questo feedback. Può eseguire questo comando da solo per vedere i risultati dell’analisi. Eseguirlo solo con il percorso applica tutte le regole predefinite.
Invoke-ScriptAnalyzer -Path .\MyScript.ps1
Può anche escludere regole usando i parametri del cmdlet.
Invoke-ScriptAnalyzer -Path .\MyScript.ps1 -ExcludeRule PSAvoidUsingCmdletAliases
Per personalizzare il comportamento di PSScriptAnalyzer senza modificare la riga di comando, può anche usare un file di configurazione. Questo file copre le stesse opzioni dei diversi parametri di Invoke-ScriptAnalyzer.
# PSScriptAnalyzerSettings.psd1
@{
Severity=@('Error','Warning')
ExcludeRules=@('PSAvoidUsingCmdletAliases', 'PSAvoidUsingWriteHost')
}
Può usare i file di impostazioni dello script analyzer passando il parametro -Settings a Invoke-ScriptAnalyzer.
Invoke-ScriptAnalyzer -Path MyScript.ps1 -Settings PSScriptAnalyzerSettings.psd1
Può anche usare questo file di impostazioni con VS Code impostando PowerShell > Script Analysis: Settings Path su PSScriptAnalyzerSettings.psd1.
Regole personalizzate
Le regole personalizzate sono definite tramite moduli PowerShell. Possono accettare un elenco di token o un albero della sintassi astratta (AST) e restituire record di diagnostica. Ad esempio, in PowerShell Universal abbiamo una regola che verifica l’uso di variabili integrate come $PSUEnvironment o $UniversalClient. Assegnare tali variabili può causare un comportamento indefinito, quindi vogliamo che gli utenti lo sappiano subito quando tentano di sovrascriverle.
Il primo passo è creare un nuovo file di modulo .psm1 e definire una funzione che analizzerà lo script. In questo esempio abbiamo scelto Universal.Rules.psm1 come nome del file e definito la funzione Measure-PSUBuiltInVariables. La guida basata sui commenti è obbligatoria e ci sono alcuni dettagli specifici di questa funzione da tenere presenti.
Per prima cosa, deve includere l’attributo OutputType per specificare il tipo di oggetto che la funzione restituirà. In questo caso restituirà un array di oggetti Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord. Deve anche accettare un oggetto ScriptBlockAst come parametro. Questo oggetto rappresenta il blocco di script dello script in fase di analisi.
<#
.SYNOPSIS
Locates built-in PowerShell Universal variables
.DESCRIPTION
Checks to make sure that built-in PowerShell Universal variables are not being used in the script.
.EXAMPLE
Measure-PSUBuiltInVariables -ScriptBlockAst $ScriptBlockAst
.INPUTS
[System.Management.Automation.Language.ScriptBlockAst]
.OUTPUTS
[Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]]
.NOTES
None
#>
function Measure-PSUBuiltInVariables {
[CmdletBinding()]
[OutputType([Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
Param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.Language.ScriptBlockAst]
$ScriptBlockAst
)
Il corpo di questa funzione svolge il lavoro principale di analisi del blocco di script. Nel nostro esempio controlliamo l’AST per trovare le istruzioni di assegnazione. Se troviamo istruzioni di assegnazione, controlliamo poi se il lato sinistro dell’assegnazione è una variabile. In tal caso, usiamo poi un metodo statico per verificare se si tratta di una delle variabili integrate di PowerShell Universal.
Se le condizioni sono soddisfatte, creiamo nuovi oggetti DiagnosticRecord e popoliamo le informazioni necessarie. $_.Extent è importante perché indica agli editor, come VS Code o Monaco, quale parte dello script evidenziare con l’avviso o l’errore.
Process {
$results = @()
try {
#region Define predicates to find ASTs.
[ScriptBlock]$predicate1 = {
param ([System.Management.Automation.Language.Ast]$Ast)
if ($Ast -is [System.Management.Automation.Language.AssignmentStatementAst]) {
if ($Ast.Left -is [System.Management.Automation.Language.VariableExpressionAst]) {
return [PowerShellUniversal.BuiltInVariables]::IsBuiltInVariable($Ast.Left.VariablePath.UserPath)
}
}
return $false
}
#endregion
#region Finds ASTs that match the predicate.
[System.Management.Automation.Language.Ast[]]$methodAst = $ScriptBlockAst.FindAll($predicate1, $true)
$methodAst | ForEach-Object {
$result = New-Object `
-Typename "Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic.DiagnosticRecord" `
-ArgumentList "Overriding built in PowerShell Universal variables can cause undefined behavior.", $_.Extent, $PSCmdlet.MyInvocation.InvocationName, Warning, $null
$results += $result
}
return $results
#endregion
}
catch {
$PSCmdlet.ThrowTerminatingError($PSItem)
}
}
Infine, ci assicuriamo di esportare la funzione dal nostro modulo.
Export-ModuleMember -Function Measure-PSUBuiltInVariables
All’interno di PowerShell Universal usiamo Invoke-ScriptAnalyzer per eseguire l’analisi del codice. Mentre digita nell’editor, questa funzione viene chiamata per fornire un feedback in tempo reale. Per usare la nostra regola personalizzata, passiamo il parametro -CustomRulePath a Invoke-ScriptAnalyzer.
Invoke-ScriptAnalyzer -ScriptDefinition $code -CustomRulePath $InstallDir\Modules\Universal.Rules\Universal.Rules.psm1 -IncludeDefaultRules
Elaboriamo poi l’output di PSScriptAnalyzer per fornire un feedback all’utente.
Ha idee per regole personalizzate per PowerShell Universal? Ce lo faccia sapere.
Pronto a iniziare a creare? Scarichi PowerShell Universal.

Adam Driscoll