Condividi tramite


about_Debuggers

Descrizione breve

Descrive il debugger di PowerShell.

Descrizione lunga

Il debug è il processo di analisi di uno script durante l'esecuzione per identificare e correggere gli errori nelle istruzioni dello script. Il debugger di PowerShell consente di esaminare e identificare errori e inefficienze negli script, nelle funzioni, nei comandi, nelle configurazioni DSC (Desired State Configuration) di PowerShell o nelle espressioni.

A partire da PowerShell 5.0, il debugger di PowerShell è stato aggiornato per eseguire il debug di script, funzioni, comandi, configurazioni o espressioni in esecuzione nella console o in Windows PowerShell Integrated Scripting Environment (ISE) nei computer remoti.

Nota

Windows PowerShell ISE supporta solo Windows PowerShell. Per PowerShell 6 e versioni successive è necessario usare Visual Studio Code con l'estensione per PowerShell. Per altre informazioni, vedere Debug con Visual Studio Code.

Cmdlet del debugger

Il debugger di PowerShell include il set di cmdlet seguente:

  • Set-PSBreakpoint: imposta punti di interruzione su righe, variabili e comandi.
  • Get-PSBreakpoint: ottiene i punti di interruzione nella sessione corrente.
  • Disable-PSBreakpoint: disattiva i punti di interruzione nella sessione corrente.
  • Enable-PSBreakpoint: abilita nuovamente i punti di interruzione nella sessione corrente.
  • Remove-PSBreakpoint: elimina i punti di interruzione dalla sessione corrente.
  • Get-PSCallStack: visualizza lo stack di chiamate corrente.

Avvio e arresto del debugger

Per avviare il debugger, impostare uno o più punti di interruzione, quindi eseguire lo script, il comando o la funzione di cui si vuole eseguire il debug.

Quando si raggiunge un punto di interruzione, l'esecuzione viene arrestata e il controllo viene trasformato nel debugger.

Per arrestare il debugger, eseguire lo script, il comando o la funzione fino al completamento. In alternativa, digitare stop o t.

Comandi del debugger

Quando si usa il debugger nella console di PowerShell, usare i comandi seguenti per controllare l'esecuzione. In Windows PowerShell ISE usare i comandi nel menu Debug.

Nota

Per informazioni su come usare il debugger in altre applicazioni host, vedere la documentazione dell'applicazione host.

  • s, StepInto: esegue l'istruzione successiva e quindi si arresta.

  • v, StepOver: esegue l'istruzione successiva, ma ignora le funzioni e le chiamate. Le istruzioni ignorate vengono eseguite, ma non una alla volta.

  • Ctrl+Break: (Interrompi tutto in ISE) Suddivide in uno script in esecuzione all'interno della console di PowerShell o in Windows PowerShell ISE. Si noti che CTRL+Interrompi in Windows PowerShell 2.0, 3.0 e 4.0 chiude il programma. Interrompi tutto funziona sia su script locali che remoti in esecuzione interattiva.

  • o, StepOut: esce dalla funzione corrente; fino a un livello se annidato. Se nel corpo principale continua fino alla fine o al punto di interruzione successivo. Le istruzioni ignorate vengono eseguite, ma non una alla volta.

  • c, Continue: continua l'esecuzione fino al completamento dello script o fino al raggiungimento del punto di interruzione successivo. Le istruzioni ignorate vengono eseguite, ma non una alla volta.

  • l, List: visualizza la parte dello script in esecuzione. Per impostazione predefinita, visualizza la riga corrente, cinque righe precedenti e 10 righe successive. Per continuare a elencare lo script, premere INVIO.

  • l <m>, List: visualizza 16 righe dello script che iniziano con il numero di riga specificato da <m>.

  • l <m> <n>, List: visualizza <n> le righe dello script, a partire dal numero di riga specificato da <m>.

  • q, Stop, , Exit: arresta l'esecuzione dello script ed esce dal debugger. Se si esegue il debug di un processo eseguendo il Debug-Job cmdlet , il Exit comando scollega il debugger e consente al processo di continuare l'esecuzione.

  • k, Get-PsCallStack: visualizza lo stack di chiamate corrente.

  • <Enter>: ripete l'ultimo comando se è Step (s), StepOver (v) o List (l). In caso contrario, rappresenta un'azione di invio.

  • ?, h: visualizza la Guida del comando del debugger.

Per uscire dal debugger, è possibile usare Stop (q).

A partire da PowerShell 5.0, è possibile eseguire il comando Exit per uscire da una sessione di debug annidata avviata eseguendo Debug-Job o Debug-Runspace.

Usando questi comandi del debugger, è possibile eseguire uno script, arrestarsi in un punto di preoccupazione, esaminare i valori delle variabili e lo stato del sistema e continuare a eseguire lo script fino a quando non è stato identificato un problema.

Nota

Se si esegue un'istruzione con un operatore di reindirizzamento, ad esempio >, il debugger di PowerShell esegue i passaggi per tutte le istruzioni rimanenti nello script.

Visualizzazione dei valori delle variabili di script

Mentre si è nel debugger, è anche possibile immettere i comandi, visualizzare il valore delle variabili, usare i cmdlet ed eseguire script nella riga di comando. È possibile visualizzare il valore corrente di tutte le variabili nello script di cui è in corso il debug, ad eccezione delle variabili automatiche seguenti:

$_
$Args
$Input
$MyInvocation
$PSBoundParameters

Quando si visualizza il valore di una di queste variabili, si ottiene il valore di tale variabile per una pipeline interna usata dal debugger, non il valore della variabile nello script.

Per visualizzare il valore di queste variabili per lo script di cui è in corso il debug, aggiungere righe allo script per salvare questi valori in una nuova variabile. Impostare il punto di interruzione dopo queste nuove righe. È quindi possibile visualizzare il valore della nuova variabile.

ad esempio:

$scriptArgs = $Args
$scriptname = $MyInvocation.PSCommandPath

Ambiente del debugger

Quando si raggiunge un punto di interruzione, immettere l'ambiente del debugger. Il prompt dei comandi cambia in modo che inizi con "[DBG]:". In alcune applicazioni host, ad esempio la console di PowerShell, viene aperto un prompt annidato per il debug. È possibile rilevare il prompt annidato ripetendo caratteri maggiori di (ASCII 62) visualizzati al prompt dei comandi.

Per altre informazioni sulla personalizzazione del prompt, vedere about_Prompts.

È possibile trovare il livello di annidamento usando la $NestedPromptLevel variabile automatica. La variabile automatica, $PSDebugContext, è definita nell'ambito locale. È possibile usare la presenza della $PSDebugContext variabile per determinare se si esegue all'interno del debugger.

Ad esempio:

if ($PSDebugContext) {"Debugging"} else {"Not Debugging"}

È possibile usare il valore della $PSDebugContext variabile nel debug.

[DBG]: PS>>> $PSDebugContext.InvocationInfo

Name   CommandLineParameters  UnboundArguments  Location
----   ---------------------  ----------------  --------
=      {}                     {}                C:\ps-test\vote.ps1 (1)

Debug e ambito

L'interruzione nel debugger non modifica l'ambito in cui si sta operando, ma quando si raggiunge un punto di interruzione in uno script, si passa all'ambito dello script. L'ambito dello script è un elemento figlio dell'ambito in cui è stato eseguito il debugger.

Per trovare le variabili e gli alias definiti nell'ambito dello script, usare il parametro Scope dei Get-Alias cmdlet o Get-Variable .

Ad esempio, il comando seguente ottiene le variabili nell'ambito locale (script):

Get-Variable -scope 0

Si tratta di un modo utile per visualizzare solo le variabili definite nello script e definite durante il debug.

Debug nella riga di comando

Quando si imposta un punto di interruzione di variabile o un punto di interruzione del comando, è possibile impostare il punto di interruzione solo in un file di script. Tuttavia, per impostazione predefinita, il punto di interruzione viene impostato su qualsiasi elemento eseguito nella sessione corrente.

Ad esempio, se si imposta un punto di interruzione sulla $name variabile, il debugger si interrompe su qualsiasi $name variabile in qualsiasi script, comando, funzione, cmdlet script o espressione eseguita fino a quando non si disabilita o si rimuove il punto di interruzione.

In questo modo è possibile eseguire il debug degli script in un contesto più realistico in cui potrebbero essere influenzati da funzioni, variabili e altri script nella sessione e nel profilo dell'utente.

I punti di interruzione di riga sono specifici dei file di script, quindi vengono impostati solo nei file di script.

Funzioni di debug

Quando si imposta un punto di interruzione su una funzione con beginsezioni , processe end , il debugger si interrompe alla prima riga di ogni sezione.

Ad esempio:

function test-cmdlet {
    begin {
        write-output "Begin"
    }
    process {
        write-output "Process"
    }
    end {
        write-output "End"
    }
}

C:\PS> Set-PSBreakpoint -command test-cmdlet

C:\PS> test-cmdlet

Begin
Entering debug mode. Use h or ? for help.

Hit Command breakpoint on 'prompt:test-cmdlet'

test-cmdlet

[DBG]: C:\PS> c
Process
Entering debug mode. Use h or ? for help.

Hit Command breakpoint on 'prompt:test-cmdlet'

test-cmdlet

[DBG]: C:\PS> c
End
Entering debug mode. Use h or ? for help.

Hit Command breakpoint on 'prompt:test-cmdlet'

test-cmdlet

[DBG]: C:\PS>

Debug di script remoti

È possibile eseguire Enter-PSSession per avviare una sessione remota interattiva di PowerShell in cui è possibile impostare punti di interruzione e eseguire il debug di file di script e comandi nel computer remoto. Enter-PSSession consente di riconnettere una sessione disconnessa che esegue uno script o un comando in un computer remoto. Se lo script in esecuzione raggiunge un punto di interruzione, la sessione client avvia automaticamente il debugger. Se la sessione disconnessa che esegue uno script ha già raggiunto un punto di interruzione, Enter-PSSession avvia automaticamente il debugger della riga di comando quando si riconnette alla sessione.

Nell'esempio seguente viene illustrato come funziona. I punti di interruzione sono stati impostati alle righe 6, 11, 22 e 25 dello script. All'avvio del debugger sono presenti due modifiche che identificano il prompt:

  • Nome del computer in cui è in esecuzione la sessione
  • Richiesta dbg che consente di sapere di essere in modalità di debug
Enter-PSSession -Cn localhost
[localhost]: PS C:\psscripts> Set-PSBreakpoint .\ttest19.ps1 6,11,22,25

ID Script          Line     Command          Variable          Action
-- ------          ----     -------          --------          ------
0 ttest19.ps1          6
1 ttest19.ps1          11
2 ttest19.ps1          22
3 ttest19.ps1          25

[localhost]: PS C:\psscripts> .\ttest19.ps1
Hit Line breakpoint on 'C:\psscripts\ttest19.ps1:11'

At C:\psscripts\ttest19.ps1:11 char:1
+ $winRMName = "WinRM"
# + ~

[localhost]: [DBG]: PS C:\psscripts>> list

6:      1..5 | foreach { sleep 1; Write-Output "hello2day $_" }
7:  }
# 8:

9:  $count = 10
10:  $psName = "PowerShell"
11:* $winRMName = "WinRM"
12:  $myVar = 102
# 13:

14:  for ($i=0; $i -lt $count; $i++)
15:  {
16:      sleep 1
17:      Write-Output "Loop iteration is: $i"
18:      Write-Output "MyVar is $myVar"
# 19:

20:      hello2day
# 21:


[localhost]: [DBG]: PS C:\psscripts>> stepover
At C:\psscripts\ttest19.ps1:12 char:1
+ $myVar = 102
# + ~

[localhost]: [DBG]: PS C:\psscripts>> quit
[localhost]: PS C:\psscripts> Exit-PSSession
PS C:\psscripts>

Esempi

Questo script di test rileva la versione di PowerShell e visualizza un messaggio appropriato per la versione. Include una funzione, una chiamata di funzione e una variabile.

Il comando seguente visualizza il contenuto del file di script di test:

PS C:\PS-test>  Get-Content test.ps1

function psversion {
  "PowerShell " + $PSVersionTable.PSVersion
  if ($PSVersionTable.PSVersion.Major -lt 7) {
    "Upgrade to PowerShell 7!"
  }
  else {
    "Have you run a background job today (start-job)?"
  }
}

$scriptName = $MyInvocation.PSCommandPath
psversion
"Done $scriptName."

Per iniziare, impostare un punto di interruzione a un punto di interesse per lo script, ad esempio una riga, un comando, una variabile o una funzione.

Per iniziare, creare un punto di interruzione di riga nella prima riga dello script Test.ps1 nella directory corrente.

PS C:\ps-test> Set-PSBreakpoint -line 1 -script test.ps1

Il comando restituisce un oggetto System.Management.Automation.LineBreakpoint .

Column     : 0
Line       : 1
Action     :
Enabled    : True
HitCount   : 0
Id         : 0
Script     : C:\ps-test\test.ps1
ScriptName : C:\ps-test\test.ps1

A questo punto, avviare lo script.

PS C:\ps-test> .\test.ps1

Quando lo script raggiunge il primo punto di interruzione, il messaggio del punto di interruzione indica che il debugger è attivo. Descrive il punto di interruzione e visualizza in anteprima la prima riga dello script, ovvero una dichiarazione di funzione. Il prompt dei comandi cambia anche per indicare che il debugger dispone del controllo .

La riga di anteprima include il nome dello script e il numero di riga del comando visualizzato in anteprima.

Entering debug mode. Use h or ? for help.

Hit Line breakpoint on 'C:\ps-test\test.ps1:1'

test.ps1:1   function psversion {
DBG>

Usare il comando Step (s) per eseguire la prima istruzione nello script e per visualizzare in anteprima l'istruzione successiva. L'istruzione successiva usa la $MyInvocation variabile automatica per impostare il valore della $scriptName variabile sul percorso e sul nome file del file di script.

DBG> s
test.ps1:11  $scriptName = $MyInvocation.PSCommandPath

A questo punto, la $scriptName variabile non viene popolata, ma è possibile verificare il valore della variabile visualizzandone il valore. In questo caso il valore è $null.

DBG> $scriptname
DBG>

Usare un altro Step comando (s) per eseguire l'istruzione corrente e visualizzare in anteprima l'istruzione successiva nello script. L'istruzione successiva chiama la psversion funzione .

DBG> s
test.ps1:12  psversion

A questo punto, la $scriptName variabile viene popolata, ma si verifica il valore della variabile visualizzandone il valore. In questo caso, il valore viene impostato sul percorso dello script.

DBG> $scriptName
C:\ps-test\test.ps1

Usare un altro comando Step per eseguire la chiamata di funzione. Premere INVIO oppure digitare "s" per Passaggio.

DBG> s
test.ps1:2       "PowerShell " + $PSVersionTable.PSVersion

Il messaggio di debug include un'anteprima dell'istruzione nella funzione . Per eseguire questa istruzione e per visualizzare in anteprima l'istruzione successiva nella funzione, è possibile usare un Step comando . In questo caso, tuttavia, usare un comando StepOut (o). Completa l'esecuzione della funzione (a meno che non raggiunga un punto di interruzione) e passi all'istruzione successiva nello script.

DBG> o
Windows PowerShell 2.0
Have you run a background job today (start-job)?
test.ps1:13  "Done $scriptName"

Poiché si usa l'ultima istruzione nello script, i comandi Step, StepOut e Continue hanno lo stesso effetto. In questo caso, usare StepOut (o).

Done C:\ps-test\test.ps1
PS C:\ps-test>

Il comando StepOut esegue l'ultimo comando. Il prompt dei comandi standard indica che il debugger ha chiuso e restituito il controllo al processore di comandi.

Eseguire di nuovo il debugger. Prima di tutto, per eliminare il punto di interruzione corrente, usare i Get-PsBreakpoint cmdlet e Remove-PsBreakpoint . Se si ritiene di riutilizzare il punto di Remove-PsBreakpointinterruzione, usare il Disable-PsBreakpoint cmdlet anziché .)

PS C:\ps-test> Get-PSBreakpoint| Remove-PSBreakpoint

È possibile abbreviare il comando in

PS C:\ps-test> gbp | rbp

In alternativa, eseguire il comando scrivendo una funzione, ad esempio la funzione seguente:

function delbr { gbp | rbp }

Creare ora un punto di interruzione nella $scriptname variabile.

PS C:\ps-test> Set-PSBreakpoint -variable scriptname -script test.ps1

È possibile abbreviare il comando come segue:

PS C:\ps-test> sbp -v scriptname -s test.ps1

A questo punto, avviare lo script. Lo script raggiunge il punto di interruzione della variabile. La modalità predefinita è Write, quindi l'esecuzione si arresta immediatamente prima dell'istruzione che modifica il valore della variabile.

PS C:\ps-test> .\test.ps1
Hit Variable breakpoint on 'C:\ps-test\test.ps1:$scriptName'
(Write access)

test.ps1:11  $scriptName = $MyInvocation.PSCommandPath
DBG>

Visualizzare il valore corrente della $scriptName variabile , ovvero $null.

DBG> $scriptName
DBG>

Usare un Step comando (s) per eseguire l'istruzione che popola la variabile. Visualizzare quindi il nuovo valore della $scriptName variabile.

DBG> $scriptName
C:\ps-test\test.ps1

Usare un comando Step (s) per visualizzare in anteprima l'istruzione successiva nello script.

DBG> s
test.ps1:12  psversion

L'istruzione successiva è una chiamata alla psversion funzione . Per ignorare la funzione ma comunque eseguirla, usare un StepOver comando (v). Se si è già nella funzione quando si usa StepOver, non è efficace. Viene visualizzata la chiamata di funzione, ma non viene eseguita.

DBG> v
Windows PowerShell 2.0
Have you run a background job today (start-job)?
test.ps1:13  "Done $scriptName"

Il StepOver comando esegue la funzione e visualizza l'anteprima dell'istruzione successiva nello script, che stampa la riga finale.

Usare un Stop comando (t) per uscire dal debugger. Il prompt dei comandi ripristina il prompt dei comandi standard.

C:\ps-test>

Per eliminare i punti di interruzione, usare i Get-PsBreakpoint cmdlet e Remove-PsBreakpoint .

PS C:\ps-test> Get-PSBreakpoint| Remove-PSBreakpoint

Creare un nuovo punto di interruzione del comando nella psversion funzione.

PS C:\ps-test> Set-PSBreakpoint -command psversion -script test.ps1

È possibile abbreviare questo comando per:

PS C:\ps-test> sbp -c psversion -s test.ps1

Eseguire ora lo script.

PS C:\ps-test> .\test.ps1
Hit Command breakpoint on 'C:\ps-test\test.ps1:psversion'

test.ps1:12  psversion
DBG>

Lo script raggiunge il punto di interruzione alla chiamata di funzione. A questo punto, la funzione non è ancora stata chiamata. In questo modo è possibile usare il parametro Action di Set-PSBreakpoint per impostare le condizioni per l'esecuzione del punto di interruzione o per eseguire attività preliminari o diagnostiche, ad esempio l'avvio di un log o la chiamata di uno script di diagnostica o di sicurezza.

Per impostare un'azione, usare un comando Continue (c) per uscire dallo script e un Remove-PsBreakpoint comando per eliminare il punto di interruzione corrente. I punti di interruzione sono di sola lettura, quindi non è possibile aggiungere un'azione al punto di interruzione corrente.

DBG> c
Windows PowerShell 2.0
Have you run a background job today (start-job)?
Done C:\ps-test\test.ps1

PS C:\ps-test> Get-PSBreakpoint| Remove-PSBreakpoint
PS C:\ps-test>

A questo punto, creare un nuovo punto di interruzione del comando con un'azione. Il comando seguente imposta un punto di interruzione del comando con un'azione che registra il valore della $scriptName variabile quando viene chiamata la funzione. Poiché la break parola chiave non viene usata nell'azione, l'esecuzione non si arresta. Il backtick (`) è il carattere di continuazione della riga.

PS C:\ps-test> Set-PSBreakpoint -command psversion -script test.ps1  `
-action { add-content "The value of `$scriptName is $scriptName." `
-path action.log}

È anche possibile aggiungere azioni che impostano condizioni per il punto di interruzione. Nel comando seguente il punto di interruzione del comando viene eseguito solo se i criteri di esecuzione sono impostati su RemoteSigned, i criteri più restrittivi che consentono comunque di eseguire gli script.

PS C:\ps-test> Set-PSBreakpoint -script test.ps1 -command psversion `
-action { if ((Get-ExecutionPolicy) -eq "RemoteSigned") { break }}

La break parola chiave nell'azione indica al debugger di eseguire il punto di interruzione. È anche possibile usare la continue parola chiave per indirizzare l'esecuzione del debugger senza interruzioni. Poiché la parola chiave predefinita è continue, è necessario specificare per arrestare break l'esecuzione.

Eseguire ora lo script.

PS C:\ps-test> .\test.ps1
Hit Command breakpoint on 'C:\ps-test\test.ps1:psversion'

test.ps1:12  psversion

Poiché i criteri di esecuzione sono impostati su RemoteSigned, l'esecuzione si arresta alla chiamata di funzione.

A questo punto, è possibile controllare lo stack di chiamate. Usare il Get-PsCallStack cmdlet o il Get-PsCallStack comando debugger (k). Il comando seguente ottiene lo stack di chiamate corrente.

DBG> k
2: prompt
1: .\test.ps1: $args=[]
0: prompt: $args=[]

Questo esempio illustra solo alcuni dei molti modi per usare il debugger di PowerShell.

Altre funzionalità di debug in PowerShell

Oltre al debugger di PowerShell, PowerShell include diverse altre funzionalità che è possibile usare per eseguire il debug di script e funzioni.

  • Il Set-PSDebug cmdlet offre funzionalità di debug di script molto di base, tra cui istruzioni e traccia.

  • Usare il Set-StrictMode cmdlet per rilevare i riferimenti alle variabili non inizializzate, ai riferimenti a proprietà inesistenti di un oggetto e alla sintassi della funzione non valida.

  • Aggiungere istruzioni di diagnostica a uno script, ad esempio istruzioni che visualizzano il valore di variabili, istruzioni che leggono l'input dalla riga di comando o istruzioni che segnalano l'istruzione corrente. Usare i cmdlet che contengono il verbo Write per questa attività, ad esempio Write-Host, Write-DebugWrite-Warning, e Write-Verbose.

Vedi anche