出力 Write-Host 出力オブジェクト、文字列、PowerShell 文字起こしとの混在は複雑です。 スクリプトと、予期しない結果が発生する可能性がある PowerShell パイプラインでの文字起こしのしくみの間には、微妙な相互作用があります。
スクリプトからオブジェクトを出力すると、それらのオブジェクトの書式設定は Out-Defaultによって処理されます。
ただし、書式設定は、スクリプトが完了し、文字起こしが停止した後に発生する可能性があります。 つまり、出力は文字起こしされません。 文字列の処理方法は異なります。 文字列の出力が書式設定によって渡される場合がありますが、毎回ではありません。
Write-Host は、ホスト プロセスへの即時書き込みを行います。
Write-Output は書式設定システムを介して送信されます。 複雑なオブジェクトの出力とホストへの書き込みを組み合わせると、トランスクリプトに記録される内容を予測するのが困難になります。
シナリオ 1 - 他のすべての操作の後に構造化オブジェクトを出力する
次のスクリプトとその出力について考えてみましょう。
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
コンソールへの出力には予想される出力が表示されますが、期待した順序ではありません。
Write-Host 4は、Get-Locationがホストに直接書き込まれるよう最適化されているため、Write-Host前に表示されます。 文字起こしには、トランスクリプト ファイルとコンソールに出力をコピーするコードがあります。 その後、通常の出力としての Get-Location と Write-Output 5 がスクリプトの出力として送信されます。
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
**********************
スクリプトが終了する前に文字起こしがオフになっているため、トランスクリプトにはレンダリングされません。 オブジェクトは、パイプライン内の次のコンシューマーに送信されました。 この場合、Out-Default は PowerShell が自動的に挿入したものです。 さらに複雑にするために、文字列の出力も書式設定システムで最適化されます。 最初の Write-Output 2 がトランスクリプトによって出力およびキャプチャされます。 ただし、 Get-Location オブジェクトを挿入すると、実際の書式設定が必要なもののスタックに出力がプッシュされます。これにより、書式設定が必要な残りのオブジェクトに対して少しの状態が設定されます。 これが、2 番目の Write-Output 5 がトランスクリプトに追加されない理由です。
シナリオ 2 - オブジェクト放出を冒頭に設定する
次のスクリプトとその出力について考えてみましょう。
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
Write-Hostコマンドが何よりも前に発生し、オブジェクトが出始めることがわかります。文字列のWrite-Outputにより、オブジェクトが強制的に画面にレンダリングされますが、トランスクリプトにはWrite-Hostの出力のみが含まれていることに注意してください。 これは、スクリプトが文字起こしをオフにした後、それらの文字列オブジェクトが Out-Default にパイプされて書式設定されるためです。
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
**********************
シナリオ 3 - スクリプトの最後に出力されるオブジェクト
このシナリオでは、複雑なオブジェクトの出力はスクリプトの最後にあります。
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
Write-Host と Write-Output の両方の文字列出力によりトランスクリプトに変換されます。 ただし、 Get-Location からの出力は、文字起こしが停止した後に発生します。
**********************
PowerShell transcript start
Start time: 20220606100342
**********************
Transcript started, output file is scenario3.log
1
2
4
5
**********************
PowerShell transcript end
End time: 20220606100342
**********************
完全な文字起こしを保証する方法
この例は、元のシナリオでは若干異なりますが、これですべてがトランスクリプトに記録されます。 元のコードはスクリプト ブロックにラップされ、フォーマッタは 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
最後の Write-Host 呼び出しはまだ順序が外れていることに注意してください。これは、出力ストリームに入らない Write-Host の最適化が原因です。
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
**********************
PowerShell