Windows Server 2025 / Gestire gli errori PowerShell e registrare le esecuzioni
Per individuare errori e risultati parziali nelle attività PowerShell, combinare try, catch e finally con una gestione esplicita degli errori e un log distinto per ogni esecuzione. Il completamento di un comando non dimostra, da solo, che l’intera attività amministrativa sia riuscita.
Rendere visibili gli errori
Questo esercizio legge un file e scrive un log senza modificare ruoli, servizi o rete del server. Uno script reale di installazione o gestione degli account deve registrare anche quali modifiche rimangono dopo un errore intermedio. Entrare in catch non annulla automaticamente le azioni precedenti.
Alcuni errori consentono a PowerShell di continuare e, per impostazione predefinita, non attivano catch. Inserire un comando in try non basta: -ErrorAction Stop trasforma gli errori non terminanti supportati in errori terminanti intercettabili. La documentazione sulla gestione degli errori PowerShell spiega questa distinzione.
Preparare l’input e lo script completo
Creare prima C:\LabScripts e salvare in C:\LabScripts\input.txt una sola riga contenente il testo letterale lab ready. Salvare tutto il codice seguente come C:\LabScripts\Read-LabFile.ps1, verificando le estensioni .txt e .ps1. Usare UTF-8; aggiungendo caratteri non ASCII allo script, scegliere UTF-8 con indicatore dell’ordine dei byte (BOM, byte order mark), secondo la documentazione sulla codifica. Eseguire con Windows PowerShell 5.1 e autorizzazioni per leggere l’input e creare o scrivere C:\LabLogs. Lo script salva dati strutturati in formato JSON (JavaScript Object Notation), usando un nome di file con data, ora e identificatore breve.
param(
[Parameter(Mandatory=$true)]
[string]$InputPath
)
$logDirectory = 'C:\LabLogs'
New-Item -ItemType Directory -Path $logDirectory -Force -ErrorAction Stop | Out-Null
$runLabel = (Get-Date -Format 'yyyyMMdd-HHmmss') + '-' + ([guid]::NewGuid().ToString('N').Substring(0,6))
$logPath = Join-Path $logDirectory ($runLabel + '.json')
$result = [ordered]@{
StartedAt = (Get-Date).ToString('o')
ComputerName = $env:COMPUTERNAME
InputPath = $InputPath
Success = $false
LineCount = $null
ErrorId = $null
ErrorMessage = $null
}
$exitStatus = 0
try {
$lines = @(Get-Content -LiteralPath $InputPath -ErrorAction Stop)
$result.LineCount = $lines.Count
$result.Success = $true
}
catch {
$result.ErrorId = $_.FullyQualifiedErrorId
$result.ErrorMessage = $_.Exception.Message
$exitStatus = 1
Write-Warning $result.ErrorMessage
}
finally {
$result.FinishedAt = (Get-Date).ToString('o')
$result | ConvertTo-Json | Set-Content -LiteralPath $logPath -Encoding UTF8 -ErrorAction Stop
}
Write-Output $logPath
exit $exitStatus
Confrontare successo ed errore nelle stesse condizioni
Eseguire le righe da una console PowerShell. Ogni powershell.exe avvia un processo figlio: exit termina quel processo e lascia disponibile la console originale. Avviare prima la lettura del file esistente e consultare subito $LASTEXITCODE; ripetere poi la coppia di comandi con missing-input.txt, che deve essere realmente assente. Non eliminare l’input valido e non modificare un file di sistema per provocare l’errore:
powershell.exe -NoProfile -File 'C:\LabScripts\Read-LabFile.ps1' -InputPath 'C:\LabScripts\input.txt'
$LASTEXITCODE
powershell.exe -NoProfile -File 'C:\LabScripts\Read-LabFile.ps1' -InputPath 'C:\LabScripts\missing-input.txt'
$LASTEXITCODE
Con l’input di una sola riga, la prima esecuzione deve restituire 0 e creare un JSON con Success=true e LineCount=1, senza dettagli di errore. Per il file inesistente sono previsti 1, Success=false e LineCount=null, con ErrorId ed ErrorMessage valorizzati. Il messaggio può variare con la lingua del sistema. Aprire con un editor di testo il JSON indicato dal percorso stampato per ciascuna esecuzione e controllare InputPath, ComputerName, StartedAt e FinishedAt. Confrontare i due nuovi log, senza confonderli con un file precedente della cartella.
Se un criterio blocca l’esecuzione dello script, rispettare i requisiti di esecuzione e firma dell’organizzazione, senza indebolire le impostazioni globali per questo esempio.
Comprendere le sezioni di gestione degli errori
| Sezione | Scopo in questo script |
|---|---|
| try | Leggere il file e registrarne il numero di righe |
| catch | Registrare identificatore e messaggio dell’errore intercettato; scegliere un codice di uscita di errore |
| finally | Tentare di salvare il risultato, sia quando la lettura riesce sia quando fallisce |
Il riferimento Microsoft a try, catch e finally spiega la gestione degli errori terminanti. In questo script C:\LabLogs viene creato prima di try: se questa preparazione fallisce, il catch successivo non intercetta l’errore. finally tenta il salvataggio, ma non garantisce spazio disponibile o autorizzazioni di scrittura. Success riguarda la lettura: verificare anche la creazione di un nuovo JSON valido. La scrittura del log usa a sua volta -ErrorAction Stop. L’assenza di un log non dimostra che l’attività si sia conclusa senza errori.
I programmi esterni restituiscono codici di uscita propri. In Windows PowerShell 5.1, un codice diverso da zero non attiva automaticamente catch. Controllare $LASTEXITCODE subito dopo il programma e, quando necessario, usare throw per generare un errore terminante. Un altro programma esterno può sostituire quel valore; -ErrorAction Stop da solo non converte i codici di uscita esterni in eccezioni.
Definire criteri per ripetere le attività in sicurezza
- Registrare server, destinazione e orari di inizio e fine.
- Verificare lo stato esistente per evitare creazioni duplicate o sovrascritture involontarie.
- Registrare separatamente i passaggi riusciti e quelli falliti.
- Escludere dai log password, token e contenuti non necessari dei file degli utenti.
- Se si implementa un rollback per annullare modifiche, documentarne l’ambito e gli eventuali errori di ripristino.
Usare nuovamente il percorso di input.txt ed eseguire lo script per verificare un nuovo codice 0 e un nuovo JSON con Success=true e LineCount=1. Conservare le evidenze necessarie prima di rimuovere esclusivamente i file temporanei identificati dell’esercizio. Aggiungere SilentlyContinue a tutti i comandi nasconde gli errori e non ne sostituisce la gestione.




