Cosa
Questo articolo fornisce una guida completa alle best practice per lo scripting in PowerShell, con focus su struttura del codice, formattazione dell’output, gestione degli errori, ottimizzazione delle prestazioni e misure di sicurezza.
Perché
Seguire le best practice nello scripting PowerShell garantisce script leggibili, manutenibili, sicuri ed efficienti. Riduce il debito tecnico, migliora la collaborazione e minimizza i rischi negli ambienti di produzione.
Come
Progettazione di Strumenti e Controller
Decidi se stai creando uno "Strumento" o un "Controller"
- Strumento: Funzioni/moduli riutilizzabili.
- Controller: Automatizza un’attività specifica, non destinato al riutilizzo.
Rendi il codice modulare
- Usa funzioni e moduli di script per massimizzare la riutilizzabilità.
Usa convenzioni di denominazione standard
- Segui il formato Verbo-Sostantivo con verbi approvati da PowerShell (
Get-Verb
).
Standardizza i nomi dei parametri
- Utilizza nomi come
$ComputerName
invece di prefissi personalizzati.
Gli strumenti devono restituire dati grezzi
- Fornisci dati minimamente elaborati per una maggiore flessibilità.
I controller devono restituire dati formattati
- Formatta l’output per report user-friendly.
Esempio
function Get-DiskInfo {
param ([string]$ComputerName)
Get-WmiObject Win32_LogicalDisk -ComputerName $ComputerName
}
Evita di reinventare la ruota
Usa cmdlet integrati come Test-Connection
invece di creare funzioni personalizzate.
# Consigliato
Test-Connection $ComputerName -Quiet
Scrittura dei Blocchi di Parametri
Scrivi sempre la documentazione di aiuto
Includi commenti con .SYNOPSIS
, .DESCRIPTION
e almeno un .EXAMPLE
.
function Test-Help {
<#
.SYNOPSIS
Esempio di corretta documentazione.
.EXAMPLE
Test-Help -MandatoryParameter "Esempio"
Esegue la funzione con un parametro obbligatorio.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Alias("MP")]
[String]$MandatoryParameter
)
}
Usa [CmdletBinding()]
Abilita parametri comuni come -Verbose
, -Debug
, -ErrorAction
.
Supporta -WhatIf e -Confirm
Per comandi che modificano lo stato, usa SupportsShouldProcess
.
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")]
param ([switch]$Force)
Tipizzazione forte dei parametri
Definisci sempre i tipi per chiarezza e validazione.
param (
[string]$Name,
[int]$Count
)
Usa [switch] correttamente
- Il valore predefinito è
$false
. - Usalo come booleano, evitando logiche complesse.
Formattazione dell’Output
Evita Write-Host se non necessario
Preferisci Write-Verbose
, Write-Debug
o Write-Output
a seconda del contesto.
Usa Write-Progress per aggiornamenti di avanzamento
Write-Progress -Activity "Elaborazione" -Status "50% completato" -PercentComplete 50
Usa file di formattazione per oggetti personalizzati
Definisci file .format.ps1xml
invece di formattazioni inline.
Restituisci un solo tipo di oggetto alla volta
Utilizza [OutputType()]
ed evita la mescolanza di tipi.
Best Practice per la Gestione degli Errori
Usa -ErrorAction Stop con i cmdlet
Forza gli errori per poterli gestire con try-catch
.
try {
Get-Item "C:\PercorsoNonValido" -ErrorAction Stop
} catch {
Write-Warning "Elemento non trovato."
}
Usa $ErrorActionPreference per operazioni non-cmdlet
Impostalo temporaneamente su 'Stop'
per operazioni rischiose.
Evita flag e $? per la gestione degli errori
Preferisci blocchi strutturati try-catch
.
Copia subito $Error[0] o $_ all’interno di catch
catch {
$errorDetails = $_
Write-Error "Si è verificato un errore: $($errorDetails.Exception.Message)"
}
Ottimizzazione delle Prestazioni
PERF-01 Misura le prestazioni quando necessario
Utilizza Measure-Command
per confrontare soluzioni.
Measure-Command {
foreach ($item in $data) { Process-Item $item }
}
PERF-02 Bilancia leggibilità e prestazioni
- Per piccoli dataset, privilegia la leggibilità.
- Per grandi volumi, considera streaming o tecniche .NET.
Leggibile ma meno performante:
$content = Get-Content -Path file.txt
foreach ($line in $content) {
Do-Something -Input $line
}
Ottimizzato:
Get-Content -Path file.txt | ForEach-Object {
Do-Something -Input $_
}
Alta performance con .NET:
$sr = New-Object System.IO.StreamReader "file.txt"
while ($sr.Peek() -ge 0) {
$line = $sr.ReadLine()
Do-Something -Input $line
}
PERF-03 Preferisci le strutture del linguaggio ai cmdlet
- Strutture (
foreach
) > Metodi .NET > Script > Cmdlet/Pipeline. - Misura sempre prima di ottimizzare.
Best Practice di Sicurezza
Usa sempre PSCredential per le credenziali
Evita password in chiaro.
param (
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
Per API:
$Insecure.SetPassword($Credential.GetNetworkCredential().Password)
Usa SecureString per dati sensibili
$Secure = Read-Host -Prompt "Inserisci dati sicuri" -AsSecureString
Conversione sicura:
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Secure)
$PlainText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
Salva le credenziali in modo sicuro
Get-Credential | Export-CliXml -Path C:\secure\cred.xml
$Credential = Import-CliXml -Path C:\secure\cred.xml
Salva stringhe criptate
ConvertFrom-SecureString -SecureString $Secure | Out-File -Path "${Env:AppData}\secure.bin"
$Secure = Get-Content -Path "${Env:AppData}\secure.bin" | ConvertTo-SecureString
Conclusione
Seguendo queste best practice di PowerShell in termini di design, documentazione, gestione dell’output, errori, prestazioni e sicurezza, potrai creare script robusti, efficienti e facilmente manutenibili. Cerca sempre il giusto equilibrio tra leggibilità, performance e sicurezza per offrire soluzioni di automazione di alta qualità.