powershell 在输出中将换行符放置在不合适的位置

powershell putting linebreaks inappropriate places in output

我有一个 PowerShell 脚本,但在继续下一行之前,某些输出在任意点被截断。这太烦人了。

例如,我可以使用 Write-Host,只要我想要,线路就会继续(注意,Team City 中的 运行 和 Team City 添加了一些前缀信息 - 但是可以观察到通过管道将输出输出到文件的相同效果):

[10:04:45] [Step 5/7]  - Found Windows Service at G:\TeamCityData\TeamCityBuildAgent-1\work2b8abc9094651e\Artefacts\windows-services\WindowsService.Dummy\WindowsService.DummyService.exe

其他时候,输出似乎在任意点被人为截断,就像它被包裹在 window 中(实际上并不存在)。

所以,这一行:

Copy-Item -Path $fullSourcePath -Destination $destPath -Recurse -Verbose -ErrorAction Stop

在 Team City 中生成此输出(添加一些前缀信息):

[10:04:46] [Step 5/7] VERBOSE: Performing the operation "Copy File" on target "Item: 
[10:04:46] [Step 5/7] G:\TeamCityData\TeamCityBuildAgent-1\work2b8abc9094651e\Artefacts\windows-services\WindowsService.Dummy\WindowsServi
[10:04:46] [Step 5/7] ce.DummyService.exe Destination: 
[10:04:46] [Step 5/7] \SERVER001\scheduled-tasks\ProductFolder\Dev\DummyWindowsService\WindowsService.DummyService.exe".
[10:04:46] [Step 5/7] VERBOSE: Performing the operation "Copy File" on target "Item: 
[10:04:46] [Step 5/7] G:\TeamCityData\TeamCityBuildAgent-1\work2b8abc9094651e\Artefacts\windows-services\WindowsService.Dummy\WindowsServi
[10:04:46] [Step 5/7] ce.DummyService.exe.config Destination: 
[10:04:46] [Step 5/7] \SERVER001\scheduled-tasks\ProductFolder\Dev\DummyWindowsService\WindowsService.DummyService.exe.config".

我该如何阻止这种荒谬的行为?我希望输出在行尾而不是文件名中间正确呈现换行符。

更新

下面的评论表明这是 TeamCity 捕获输出的方式的问题。但是,如果我直接在 PowerShell 控制台中执行类似命令并将输出通过管道传输到文件,则会发生同样的问题。

命令:

copy-item -Path F:\logs -Destination .\ -Recurse -Verbose *> F:\logs\copy-item-output-1.txt

产生这样的输出:

Performing the operation "Copy File" on target "Item: F:\logs161103-140649-ProductName.Program.log 
Destination: F:\Destination34567890abcdefghijklmnopqrstuvwxyz\this-is-a-long-path-name-to-show-wrapping-issues-with-copy-it
em\logs161103-140649-ProductName.Program.log".

如您所见,它还跨行拆分了文件路径,即使它被发送到文件,而不是控制台 window。

以下解决方案 (more than 10 years old so there might exist a smarter way recently?) 适用于 PowerShellPowerShell ISE:

$pshost = get-host
$pswindow = $pshost.ui.rawui
$newsize = $pswindow.buffersize
### do not change $newsize.height
$newsize.width = 3000               ### [int] type; max. value unknown at present
$pswindow.buffersize = $newsize

您可以将其他流重定向到输出流以提供对详细输出和其他类型输出的自定义处理:

& {
    #Script code here
    Copy-Item -Path $fullSourcePath -Destination $destPath -Recurse -Verbose -ErrorAction Stop
} *>&1 | % {
    function IsStreamType {
        param($Object, $Type)
        $Property = $_.PSObject.Properties[$Type]
        $null -ne $Property -and $Property.Value -is [bool] -and $Property.Value
    }
} {
    switch(,$_) {
        {
            $_ -is [System.Management.Automation.DebugRecord] -and
            (IsStreamType $_ WriteDebugStream)
        } {
            "Debug message: $($_.Message)"
        }
        {
            $_ -is [System.Management.Automation.VerboseRecord] -and
            (IsStreamType $_ WriteVerboseStream)
        } {
            "Verbose message: $($_.Message)"
        }
        {
            $_ -is [System.Management.Automation.WarningRecord] -and
            (IsStreamType $_ WriteWarningStream)
        } {
            "Warning message: $($_.Message)"
        }
        default { ,$_ }
    }
}

我使用 ,$_ 而不是普通的 $_ 作为预防措施,以防止在 $_ 恰好是集合对象的情况下出现 PowerShell 展开行为。