当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell 成绩单的局限性

作者:精品下载站 日期:2024-12-14 03:03:36 浏览:15 分类:玩电脑

PowerShell 成绩单的局限性


将 Write-Host 输出与输出对象、字符串和 PowerShell 转录混合起来很复杂。脚本与转录如何与 PowerShell 管道一起工作之间存在微妙的交互,这可能会产生意想不到的结果。

当您从脚本中发出对象时,这些对象的格式由 Out-Default 处理。但格式化可以在脚本完成且转录停止后进行。这意味着输出不会被转录。字符串的处理方式不同。有时字符串输出是通过格式化传递的,但并非总是如此。 Write-Host 立即写入主机进程。 Write-Object 通过格式化系统发送。将复杂对象的输出与对主机的写入结合起来使得预测记录中记录的内容变得困难。

场景 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 4Get-Location 之前可见,因为 Write-Host 已优化为直接写入主机。转录中的代码将输出复制到转录文件和控制台。然后,我们将 Get-LocationWrite-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
**********************

由于转录在脚本退出之前关闭,因此不会在转录中呈现。这些对象被发送到管道中的下一个使用者。在本例中,它是 PowerShell 自动插入的 Out-Default。更复杂的是,字符串的输出也在格式化系统中进行了优化。第一个 Write-Output 2 由转录本发出并捕获。但是插入 Get-Location 对象会导致其输出被推入需要实际格式化的内容堆栈中,这会为也可能需要格式化的任何剩余对象设置一些状态。这就是为什么第二个 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-HostWrite-Object 输出的字符串都将进入记录。但是,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
**********************

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯