ChatGPT解决这个技术问题 Extra ChatGPT

如何在 PowerShell 中输出内容

我正在从批处理文件中运行 PowerShell 脚本。该脚本获取一个网页并检查该页面的内容是否为字符串“OK”。

PowerShell 脚本向批处理脚本返回错误级别。

批处理脚本由 FTP 自动化程序 ScriptFTP 执行。如果发生错误,我可以让 ScriptFTP 通过电子邮件将完整的控制台输出发送给管理员。

在 PowerShell 脚本中,如果它不是“OK”,我想从网站输出返回值,因此错误消息将包含在控制台输出中,从而包含在状态邮件中。

我是 PowerShell 的新手,不确定要使用哪个输出函数。我可以看到三个:

写主机

写输出

写错误

写入 Windows 等效的 stdout 的正确方法是什么?


P
Pure.Krome

简单地输出一些东西是 PowerShell 是一件美丽的事情 - 也是它最大的优势之一。比如常见的Hello, World!应用程序简化为一行:

"Hello, World!"

它创建一个字符串对象,分配上述值,并且作为命令管道上的最后一项,它调用 .toString() 方法并将结果输出到 STDOUT(默认情况下)。美丽的东西。

其他 Write-* 命令特定于将文本输出到其关联的流中,并且具有它们的位置。


事实并非如此。它是一个字符串文字表达式,也是其管道中唯一的东西。因此它等价于 "Hello, World!" | Out-Host。另一方面,Out-Host 将对象发送到 PowerShell 主机进行显示,其实现取决于主机。控制台主机确实将它们发送到标准输出句柄(沿途通过 Out-Default)。然而,PowerShell ISE 将它们显示在其输出窗格中,而其他主机可能会完全执行其他操作。
对象也不会盲目地转换为字符串,而是通过一个 formatter 来决定如何处理它们。这就是为什么您会看到 Get-ChildItem 的输出以表格形式出现,而具有许多属性(例如 WMI)的结果默认为 Format-List
C
Community

我认为在这种情况下您将需要 Write-Output

如果你有一个像

Write-Output "test1";
Write-Host "test2";
"test3";

然后,如果您使用重定向输出调用脚本,例如 yourscript.ps1 > out.txt,您将在“out.txt”中的屏幕 test1\ntest3\n 上看到 test2

请注意,“test3”和 Write-Output 行将始终在您的文本中追加一个新行,并且在 PowerShell 中无法阻止这一点(也就是说,echo -n 在 PowerShell 中使用本机命令是不可能的)。如果您想要 echo -n 的功能(Bash 中的一些基本和简单的功能),请参阅 samthebest's answer

如果批处理文件运行 PowerShell 命令,它很可能会捕获 Write-Output 命令。我与系统管理员就应该将什么写入控制台以及不应该写入什么进行了“长时间的讨论”。我们现在已经同意,脚本执行成功或死亡的唯一信息必须是Write-Host,并且脚本作者可能需要了解有关执行的所有信息(更新了哪些项目,设置了哪些字段等cetera) 转到写入输出。这样,当您向系统管理员提交脚本时,他可以轻松地runthescript.ps1 >someredirectedoutput.txt 并在屏幕上看到一切是否正常。然后将“someredirectedoutput.txt”发回给开发人员。


P
Peter Mortensen

我认为以下是 Echo vs. Write-Host 的一个很好的展示。请注意 test() 实际上是如何返回一个整数数组,而不是一个容易让人相信的整数。

function test {
    Write-Host 123
    echo 456 # AKA 'Write-Output'
    return 789
}

$x = test

Write-Host "x of type '$($x.GetType().name)' = $x"

Write-Host "`$x[0] = $($x[0])"
Write-Host "`$x[1] = $($x[1])"

以上的终端输出:

123
x of type 'Object[]' = 456 789
$x[0] = 456
$x[1] = 789

我可以整天看这个...但是为什么 $x = test 只打印 123 而不是 456
Write-Output(或 echo)将指定的对象写入管道。如果 Write-Output 是管道中的最后一个命令,则对象将显示在控制台中。这是倒数第二个,是否正在通过管道传递到 return 语句并添加数组 docs.microsoft.com/en-us/powershell/module/…
S
Sara J

您可以在您的场景中使用其中的任何一个,因为它们会写入默认流(输出和错误)。如果您将输出通过管道传输到另一个命令行开关,您可能需要使用 Write-Output,它最终会在 Write-Host 中终止。

本文介绍了不同的输出选项:PowerShell O is for Output


感谢您的链接。天哪,这很复杂。如果 Write-host 是某种端点或刷新功能,我将尝试使用它并报告回来。
m
mklement0

写入 Windows 等效的标准输出的正确方法是什么?

效果,但非常不幸Windows PowerShell 和 PowerShell Core v7.2 均发送全部当通过 PowerShell 的 CLI从外部调用 时,他们的 6(!) output streams 中的 em> 到 stdout

请参阅 GitHub 问题 #7989 以讨论此有问题的行为,该问题可能不会得到修复,以保持向后兼容性。

实际上,这意味着您将输出发送到的任何 PowerShell 流都将被外部调用者视为标准输出:例如,如果您从 cmd.exe 运行以下命令,您将看不到任何输出,因为标准输出重定向到 NUL 适用同样适用于所有 PowerShell 流:C:\>powershell -noprofile -command "Write-Error error!" >NUL 但是 - 奇怪的是 - 如果你重定向 stderr,PowerShell 确实将其错误流发送到 stderr,因此使用 2> 你可以有选择地捕获错误流输出;以下输出只是 'hi' - 成功流输出 - 同时在文件 err.txt 中捕获错误流输出: C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>错误.txt

例如,如果您从 cmd.exe 运行以下命令,您将看不到任何输出,因为到 NUL 的 stdout 重定向同样适用于所有 PowerShell 流: C:\>powershell -noprofile -command "Write-Error error!" >NUL

C:\>powershell -noprofile -command "Write-Error error!" >NUL

但是 - 奇怪的是 - 如果您重定向 stderr,PowerShell 确实会将其错误流发送到 stderr,因此使用 2> 您可以有选择地捕获错误流输出;以下输出只是 'hi' - 成功流输出 - 同时在文件 err.txt 中捕获错误流输出: C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>错误.txt

C:\>powershell -noprofile -command "'hi'; Write-Error 错误!" 2>错误.txt

理想的行为是:

将 PowerShell 的成功输出流(编号 1)发送到标准输出。

将所有其他流的输出发送到 stderr,这是唯一的选择,因为在进程之间仅存在 2 个输出流 - stdout(标准输出)用于数据,stderr(标准错误)用于错误消息和所有其他类型的消息 - 例如作为状态信息 - 不是数据。

建议在您的代码中做出这种区分,即使它目前没有得到尊重。

在 PowerShell 内部:

Write-Host 用于显示输出,并绕过成功输出流 - 因此,它的输出既不能(直接)在变量中捕获,也不能抑制或重定向。它最初的意图只是创建用户反馈并创建简单的、基于控制台的用户界面(彩色输出)。由于之前无法捕获或重定向,PowerShell 版本 5 使 Write-Host 写入新引入的信息流(编号 6),因此从那时起可以捕获和重定向 Write-Host 输出。

它最初的意图只是创建用户反馈并创建简单的、基于控制台的用户界面(彩色输出)。

由于之前无法捕获或重定向,PowerShell 版本 5 使 Write-Host 写入新引入的信息流(编号 6),因此从那时起可以捕获和重定向 Write-Host 输出。

Write-Error 用于将非终止错误写入错误流(编号 2);从概念上讲,错误流相当于标准错误。

Write-Output 写入成功 [output] 流(编号 1),在概念上等同于 stdout;它是写入数据(结果)的流。但是,由于 PowerShell 的隐式输出功能,很少需要显式使用 Write-Output:任何未显式捕获、抑制或重定向的命令或表达式的输出都会自动发送到成功流;例如,Write-Output "Honey, I'm $HOME" 和 "Honey, I'm $HOME" 是等价的,后者不仅更简洁,而且速度更快。有关更多信息,请参阅此答案。

但是,由于 PowerShell 的隐式输出功能,很少需要显式使用 Write-Output:任何未显式捕获、抑制或重定向的命令或表达式的输出都会自动发送到成功流;例如,Write-Output "Honey, I'm $HOME" 和 "Honey, I'm $HOME" 是等价的,后者不仅更简洁,而且速度更快。有关更多信息,请参阅此答案。

任何未显式捕获、抑制或重定向的命令或表达式的输出都会自动发送到成功流;例如,Write-Output "Honey, I'm $HOME" 和 "Honey, I'm $HOME" 是等价的,后者不仅更简洁,而且速度更快。

有关更多信息,请参阅此答案。


j
jordan
Write-Host "Found file - " + $File.FullName -ForegroundColor Magenta

Magenta 可以是“System.ConsoleColor”枚举值之一 - Black、DarkBlue、DarkGreen、DarkCyan、DarkRed、DarkMagenta、DarkYellow、Gray、DarkGray、Blue、Green、Cyan、Red、Magenta、Yellow、White。

+ $File.FullName 是可选的,它显示了如何将变量放入字符串中。


U
Uwe Keim

您根本无法让 PowerShell 省略那些讨厌的换行符。没有执行此操作的脚本或 cmdlet。

当然,Write-Host 绝对是无稽之谈,因为您无法从中重定向/管道!您只需编写自己的:

using System;

namespace WriteToStdout
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args != null)
            {
                Console.Write(string.Join(" ", args));
            }
        }
    }
}

例如

PS C:\> writetostdout finally I can write to stdout like echo -n
finally I can write to stdout like echo -nPS C:\>

您可以在 powershell 本身中执行此操作。 [System.Console]::Write("stringy") 但是,您根本无法在 powershell 中重定向它。
你当然可以。请参阅this question