tl;dr
以下内容应该可以解决您的两个问题,这些问题源于 tf.exe 使用 ANSI 字符编码而不是预期的 OEM 编码,以及默认情况下截断输出。:
- 如果您使用的是 Windows PowerShell(仅限 Windows 的旧版 PowerShell,版本最高为 v5.1):
$correctlyCapturedOutput =
& {
$prev = [Console]::OutputEncoding
[Console]::OutputEncoding = [System.Text.Encoding]::Default
# Note the addition of /format:detailed
.\tf.exe hist '$/Test' /recursive /collection:https://TestTFS/tfs/TestCollection /noprompt /format:detailed /version:C1~T
[Console]::OutputEncoding = $prev
}
$correctlyCapturedOutput =
& {
$prev = [Console]::OutputEncoding
[Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding(
[int] ((Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage ACP).ACP)
)
# Note the addition of /format:detailed
.\tf.exe hist '$/Test' /recursive /collection:https://TestTFS/tfs/TestCollection /noprompt /format:detailed /version:C1~T
[Console]::OutputEncoding = $prev
}
This Gist包含辅助函数Invoke-WithEncoding,可以在两个PowerShell版本中将上述简化如下:
$correctlyCapturedOutput =
Invoke-WithEncoding -Encoding Ansi {
.\tf.exe hist '$/Test' /recursive /collection:https://TestTFS/tfs/TestCollection /noprompt /format:detailed /version:C1~T
}
您可以直接下载并使用以下命令定义函数(虽然我个人可以向您保证这样做是安全的,但最好先检查源代码):
# Downloads and defines function Invoke-WithEncoding in the current session.
irm https://gist.github.com/mklement0/ef57aea441ea8bd43387a7d7edfc6c19/raw/Invoke-WithEncoding.ps1 | iex
继续阅读以了解详细讨论。
关于元音变音(字符编码)问题:
虽然外部程序的输出可能打印到控制台,但当涉及到在变量中捕获输出或重定向时 - 例如在您的情况下通过管道将其发送到 Out-String - PowerShell 使用存储在 @987654337 中的字符编码将输出解码为 .NET 字符串 @。
如果[Console]::OutputEncoding 与外部程序使用的实际编码不匹配,PowerShell 将误解输出。
解决方案是(临时)将[Console]::OutputEncoding 设置为外部程序使用的实际编码。
虽然official tf.exe documentation 未讨论字符编码,但此comment on GitHub 表明tf.exe 使用系统的活动ANSI 代码页,例如美国英语或西欧系统上的Windows-1252。
应该注意ANSI代码页的使用对于控制台应用程序来说是非标准行为 ,因为控制台应用程序应使用系统的活动 OEM 代码页。顺便说一句:python 默认情况下也表现出这种非标准行为,尽管它的行为是可配置的。
顶部的解决方案显示了如何将[Console]::OutputEncoding 临时切换到活动的 ANSI 代码页的编码,以确保 PowerShell 正确解码 tf.exe 的输出。
用Out-String / Out-File 重新截断输出行(因此还有> 和>>):
-
正如Mustafa Zengin's helpful answer 指出的那样,在您的特定情况下-由于使用tf.exe-截断发生在源,即tf.exe本身按照其默认格式输出截断的数据(当还指定了/noprompt 时,隐含/format:brief)。
-
一般来说,Out-String 和 Out-File / > / >> 会根据控制台窗口宽度按情况截断或换行它们的输出行 strong>(默认为120 字符。在没有控制台的情况下):
-
由于 PowerShell 只将 外部程序 的输出解释为 文本([string] 实例),所以截断/换行不 em> 发生。
- 因此通常没有理由在外部程序输出上使用
Out-String - 除非您需要加入输出行的流(数组)以形成一个单个多行 用于进一步内存处理的字符串。
- 但是,请注意,
Out-String总是在结果字符串中添加一个尾随换行,这可能是不受欢迎的;使用(...) -join [Environment]::NewLine 来避免这种情况; Out-String 的问题行为在GitHub issue #14444 中进行了讨论。