Condividi tramite


Limitazioni delle trascrizioni di PowerShell

La combinazione Write-Host dell'output con gli oggetti di output, le stringhe e la trascrizione di PowerShell è complicata. Esiste un'interazione sottile tra lo script e il funzionamento della trascrizione con le pipeline di PowerShell che possono avere risultati imprevisti.

Quando si emettono oggetti dallo script, la formattazione di tali oggetti viene gestita da Out-Default. Tuttavia, la formattazione può verificarsi dopo il completamento dello script e la trascrizione è stata arrestata. Ciò significa che l'output non viene trascritto. Le stringhe vengono gestite in modo diverso. A volte l'output stringa viene passato attraverso la formattazione, ma non sempre. Write-Host esegue una scrittura immediata nel processo host. Write-Output viene inviato tramite il sistema di formattazione. La combinazione dell'output di oggetti complessi con operazioni di scrittura verso l'host rende difficile prevedere cosa venga registrato nella trascrizione.

Scenario 1 - Output di un oggetto strutturato dopo tutte le altre operazioni

Si consideri lo script seguente e il relativo output:

PS> Get-Content scenario1.ps1
Start-Transcript scenario1.log -UseMinimalHeader
Write-Host '1'
Write-Output '2'
Get-Location
Write-Host '4'
Write-Output '5'
Stop-Transcript

PS> ./scenario1.ps1
Transcript started, output file is scenario1.log
1
2

4
Path
----
/Users/user1/src/projects/transcript
5
Transcript stopped, output file is /Users/user1/src/projects/transcript/scenario1.log

L'output nella console mostra l'output previsto, ma non nell'ordine che ti aspetti. Write-Host 4 è visibile prima Get-Location perché Write-Host è ottimizzato per scrivere direttamente nell'host. Nella trascrizione è presente codice che copia l'output nel file di trascrizione e nella console. Avremo quindi l'output regolare di Get-Location e Write-Output 5 fornito come output dello script.

PS> Get-Content scenario1.log
**********************
PowerShell transcript start
Start time: 20191106114858
**********************
Transcript started, output file is s2
1
2

4
**********************
PowerShell transcript end
End time: 20191106114858
**********************

Poiché la trascrizione viene disattivata prima che il script termini, non appare nella trascrizione. Gli oggetti sono stati consegnati al consumatore successivo nella pipeline. In questo caso, è Out-Default, che PowerShell ha inserito automaticamente. Per complicare ulteriormente le cose, anche l'output delle stringhe viene ottimizzato nel sistema di formattazione. Il primo Write-Output 2 viene emesso e acquisito dalla trascrizione. Tuttavia, l'inserimento dell'oggetto determina il push dell'output Get-Location nello stack di elementi che richiedono una formattazione effettiva, che imposta un bit di stato per gli oggetti rimanenti che potrebbero anche richiedere la formattazione. Ecco perché il secondo Write-Output 5 non viene aggiunto alla trascrizione.

Scenario 2 - Spostare l'emissione dell'oggetto all'inizio

Si consideri lo script seguente e il relativo output:

PS> Get-Content scenario2.ps1
Start-Transcript scenario2.log -UseMinimalHeader
Get-Location
Write-Host '1'
Write-Output '2'
Get-Location
Write-Host '4'
Write-Output '5'
Stop-Transcript

PS> ./scenario2.ps1
Transcript started, output file is scenario2.log

1
4
Path
----
/Users/user1/src/projects/transcript
2
5
Transcript stopped, output file is /Users/user1/src/projects/transcript/scenario2.log

È possibile notare che i Write-Host comandi si verificano prima di tutto il resto e quindi gli oggetti iniziano a emergere. L'esecuzione di Write-Output su una stringa forza il rendering dell'oggetto sullo schermo, ma si noti che nella trascrizione è presente solo l'output di Write-Host. Ciò è dovuto al fatto che tali oggetti stringa vengono inviati tramite pipe a Out-Default per la formattazione dopo che lo script ha disattivato la trascrizione.

PS> Get-Content scenario2.log
**********************
PowerShell transcript start
Start time: 20220606094609
**********************
Transcript started, output file is s3

1
4
**********************
PowerShell transcript end
End time: 20220606094609
**********************

Scenario 3 - Oggetto generato alla fine dello script

Per questo scenario, l'output dell'oggetto complesso si trova alla fine dello script.

PS> Get-Content scenario3.ps1
Start-Transcript scenario3.log -UseMinimalHeader
Write-Host '1'
Write-Output '2'
Write-Host '4'
Write-Output '5'
Get-Location
Stop-Transcript

PS> ./scenario3.ps1
Transcript started, output file is scenario3.log
1
2
4
5

Path
----
/Users/user1/src/projects/transcript
Transcript stopped, output file is /Users/user1/src/projects/transcript/scenario3.log

L'output della stringa di entrambi Write-Host e Write-Output è incluso nella trascrizione. Tuttavia, l'output di Get-Location avviene dopo che la trascrizione si è fermata.

**********************
PowerShell transcript start
Start time: 20220606100342
**********************
Transcript started, output file is scenario3.log
1
2
4
5

**********************
PowerShell transcript end
End time: 20220606100342
**********************

Un modo per garantire la trascrizione completa

Questo esempio è una leggera variazione nello scenario originale, ma ora tutto viene registrato nella trascrizione. Il codice originale è racchiuso in un blocco di script e il formattatore è richiamato esplicitamente tramite Out-Default.

PS> Get-Content scenario4.ps1
Start-Transcript scenario4.log -UseMinimalHeader
. {
    Write-Host '1'
    Write-Output '2'
    Get-Location
    Write-Host '4'
    Write-Output '5'
} | Out-Default
Stop-Transcript

PS> ./scenario4.ps1
Transcript started, output file is scenario4.log
1
2

4
Path
----
/Users/user1/src/projects/transcript
5

Transcript stopped, output file is /Users/user1/src/projects/transcript/scenario4.log

Si noti che l'ultima chiamata Write-Host è ancora fuori sequenza, a causa dell'ottimizzazione in Write-Host che non viene inclusa nel flusso di output.

PS> Get-Content scenario4.log
**********************
PowerShell transcript start
Start time: 20220606101038
**********************
Transcript started, output file is s5
1
2

4
Path
----
/Users/user1/src/projects/transcript
5

**********************
PowerShell transcript end
End time: 20220606101038
**********************