Come il nome implica, PowerShell è molto più potente del prompt dei comandi standard di Windows. Con quel potere arriva una maggiore possibilità di confondere gli errori. Se il tuo script improvvisamente fallisce, potresti non sapere da dove cominciare a cercare cosa è andato storto. È qui che la gestione degli errori di PowerShell torna utile.
Se hai familiarità con altri linguaggi, probabilmente conosci le basi della gestione degli errori, ma ci sono alcuni aspetti specifici di PowerShell che dovrai conoscere. Ci sono quattro parti per la gestione degli errori in PowerShell: il parametro Error Action, i blocchi Try/Catch, il parametro Error Variable e la registrazione.
PowerShell Error Handling the Easy Way
Il primo passo nella gestione degli errori in PowerShell è affrontare qualcosa che ferma il tuo script nel suo percorso. Se l’errore non influisce sul resto del tuo script, potrebbe essere meglio dire a PowerShell di ignorare gli errori e andare avanti.
D’altra parte, non è sempre chiaro quando un dato cmdlet lancia un errore di terminazione. Alcune cmdlet restituiscono un errore ma non fermano il tuo script. Questo potrebbe lasciarvi in attesa che il vostro script si completi mentre produce output senza senso.
È qui che entra in gioco il parametro -ErrorAction. Lo usi per forzare un cmdlet a gestire l’errore nel modo che desideri. Se stai modificando uno script esistente, lo aggiungi alla fine della linea del cmdlet.
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Stop
Ovviamente, se state usando il cmdlet Get-ChildItem da solo, questo errore non fa molto per voi. Tuttavia, se volete fare qualcosa con i dati, sarebbe bene fermare lo script, così saprete che la ricerca è fallita e perché. In alternativa, se state facendo ricerche multiple, cambiate il parametro da Stop a SilentlyContinue, così lo script continua se una ricerca fallisce. Se vuoi vedere qual è l’errore, puoi invece usare Continue come parametro.
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction SilentlyContinue
Se preferite avere la possibilità di controllare cosa succede ogni volta che il vostro script viene eseguito, potete cambiarlo in Inquire. Quando il vostro cmdlet incontra un ostacolo, dà delle opzioni: Yes, Yes For All, Halt Command, Suspend, o Help.
Questa opzione è un po’ più flessibile ma significa che gli errori causano l’attesa del tuo input da parte dello script. Questo va bene se stai usando PowerShell per inviare un’email o qualche altro semplice compito, ma potrebbe non essere qualcosa che vuoi quando stai eseguendo un lungo processo durante la notte.
PowerShell Error Handling the Powerful Way
Il parametro ErrorAction affronta i tuoi errori in modo non complicato. Tuttavia, se state cercando un po’ più di controllo sugli errori, PowerShell vi copre ancora. Usando Try/Catch, possiamo ora ramificare lo script quando le cmdlets restituiscono un errore.
Come suggerisce il nome, Try/Catch è composto da due parti. (Tecnicamente ce n’è una terza, ma ci arriveremo tra un minuto.) La prima è la sezione Try. In questa sezione eseguirete il vostro normale codice. Userete ancora il parametro -ErrorAction, ma può essere impostato solo come Stop. Questo flag assicura che il vostro cmdlet inneschi il Catch–anche se non ha un errore di terminazione.
Try{
Get-Process "Cortana" -ErrorAction Stop
}
Try può anche impedire l’esecuzione di altri cmdlet se la ricerca fallisce. In questo caso, se stavate inviando i risultati di Get-Process a Stop-Process, una ricerca fallita impedisce l’esecuzione del secondo cmdlet.
Quindi, ora che avete creato un blocco try di cmdlets, cosa volete fare quando fallisce? Usando la metà di Catch, definirete questo.
Catch{
Write-Host "Process Not Found"
}
Come per il parametro ErrorAction, quando state facendo qualcosa di un po’ più complesso Catch sarà utile per qualcosa di più che dare un semplice fallimento, specialmente quando state facendo qualcosa di più complesso. (Nell’esempio sopra, il fallimento è forzato dall’uso del nome dell’app e non del nome del processo). Quindi assicuratevi di giocare con il blocco Try per creare una ricerca/azione di cui avete bisogno. Potete usare il blocco Catch per il vostro script per mandarvi un’email se fallisce.
La terza parte è utile se volete che qualcosa venga eseguito indipendentemente dal fatto che il vostro cmdlet abbia successo o meno. Per questo, puoi usare il blocco Finally. Lo aggiungete dopo Try e Catch e registrate quando una sezione del vostro script finisce.
La variabile di errore e la registrazione
Il tuo script ora controlla come gestisce gli errori e come risponde ad essi. Potete usarlo come compito programmato, o almeno eseguirlo quando non siete alla vostra scrivania. Tuttavia, come si può indagare su uno script fallito? Con il parametro -ErrorVariable gli errori del tuo cmdlet vengono scritti in una variabile personalizzata.
Questa è un’alternativa alla variabile di sistema $Error, che contiene tutti gli errori della sessione corrente.
La vostra cmdlet deve diventare un po’ più lunga. Per prima cosa, definite una variabile, qualcosa come $SearchError andrà bene per l’esempio. Quando chiamate SearchError nel parmetro ErrorVariable, non usate il segno del dollaro.
Anche se stai chiamando una variabile che hai creato, a causa del modo in cui funziona il parametro lo chiami senza il segno del dollaro. Poi aggiungilo alla fine della linea.
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Continue -ErrorVariable SearchError
Se aggiungi un + davanti al nome della variabile, puoi aggiungere alla variabile piuttosto che sostituirla completamente. Questo vi darà lo stesso comportamento della variabile di errore globale. Invece, puoi usare questo output e Try/Catch per scrivere un output personalizzato, e marcarlo temporalmente.
Per farlo funzionare, create un file di testo subito dopo aver impostato la variabile di errore. Fatelo con il cmdlet New-Item. Potresti voler usare l’opzione Inquire per il parametro ErrorAction. Questo ti permette di aggiungere ad un registro esistente quando il cmdlet New-Item fallisce.
$SearchLog = New-Item "~\SearchLog.txt" -type file -ErrorAction Inquire
Ora quando costruisci il tuo blocco Try/Catch, puoi usare il Catch per registrare in un file di testo. Usate Get-Date per creare il timestamp. La formattazione può essere complicata, quindi assicuratevi di copiarla dall’esempio.
Try{
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Stop -ErrorVariable SearchError
}
Catch{
Add-Content -Path $SearchLog -Value "$(Get-Date -Format dd-MM-yy-hh_mm_ss) Files not found returned error: $SearchError"
}
Ripetete questo come necessario per tutti i vostri cmdlets, e ora avete un bel log di tutti gli errori. Se volete tenere traccia delle cose che vengono eseguite con successo, potete aggiungere un simile Add-Content alla fine del blocco Try.
Questo log viene eseguito solo quando la tua cmdlet Try ha successo. Potete quindi registrare i vostri errori e successi con l’indicazione dell’ora. Il log ora ti permette di sapere tutto ciò che il tuo script ha fatto, successo o fallimento.
PowerShell non è la tua unica opzione
Mentre PowerShell è uno strumento utile per molti compiti di Windows, può essere difficile da imparare. Inoltre non è adatto a tutto. Se stai facendo la manutenzione del sistema sul tuo computer o controllando l’integrità di un file, PowerShell è utile. D’altra parte, se stai cercando di eseguire uno script per scaricare file da internet o qualche compito più generale, hai altre opzioni.
Per esempio, se vieni da un background Unix o Linux, potresti trovarti più a tuo agio usando la shell bash. Grazie al Windows Subsystem for Linux, ora puoi usare facilmente bash e altri strumenti Linux sul tuo computer Windows 10. Se questo vi sembra perfetto, non cercate oltre la nostra guida per far funzionare la shell bash su Windows 10.
Kris Wouk è un musicista, scrittore, e come si chiama quando qualcuno fa video per il web. Un appassionato di tecnologia per tutto il tempo che riesce a ricordare, ha sicuramente sistemi operativi e dispositivi preferiti, ma usa comunque tutti gli altri che può, solo per rimanere al passo.
Altro da Kris Wouk