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

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

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

在PowerShell脚本中,我希望输出来自网站的返回值,如果它不是“OK”,那么错误消息将包含在控制台输出中,从而包含在状态邮件中。

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

Write-Host 写输出 写错误

用什么东西来写入Windows的标准输出是正确的?


当前回答

用什么东西来写入Windows的标准输出是正确的?

实际上,但非常不幸的是,Windows PowerShell和PowerShell Core从v7.2开始,当从外部通过PowerShell的CLI调用时,都将它们所有的6(!)输出流发送到stdout。

See GitHub issue #7989 for a discussion of this problematic behavior, which likely won't get fixed, so as to preserve backward compatibility. In practice, this means that whatever PowerShell stream you send output to will be seen as stdout output by an external caller: E.g., if you run the following from cmd.exe, you'll see no output, because the stdout redirection to NUL applies equally to all PowerShell streams: C:\>powershell -noprofile -command "Write-Error error!" >NUL However - curiously - if you redirect stderr, PowerShell does send its error stream to stderr, so that with 2> you can capture the error-stream output selectively; the following outputs just 'hi' - the success-stream output - while capturing the error-stream output in file err.txt: C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>err.txt

理想的行为是:

将PowerShell的成功输出流(编号1)发送到标准输出。 将所有其他流的输出发送到stderr,这是唯一的选项,因为在进程之间只存在两个输出流——用于数据的stdout(标准输出),用于错误消息和所有其他类型的消息(如状态信息)的stderr(标准错误),这些消息都不是数据。 建议在您的代码中进行这种区分,即使目前还没有这样做。


在PowerShell:

Write-Host is for display output, and bypasses the success output stream - as such, its output can neither be (directly) captured in a variable nor suppressed nor redirected. Its original intent was simply to create user feedback and create simple, console-based user interfaces (colored output). Due to the prior inability to be captured or redirected, PowerShell version 5 made Write-Host write to the newly introduced information stream (number 6), so since then it is possible to capture and redirect Write-Host output. Write-Error is meant for writing non-terminating errors to the error stream (number 2); conceptually, the error stream is the equivalent of stderr. Write-Output writes to the success [output] stream (number 1), which is conceptually equivalent to stdout; it is the stream to write data (results) to. However, explicit use of Write-Output is rarely needed due to PowerShell's implicit output feature: Output from any command or expression that isn't explicitly captured, suppressed or redirected is automatically sent to the success stream; e.g., Write-Output "Honey, I'm $HOME" and "Honey, I'm $HOME" are equivalent, with the latter not only being more concise, but also faster. See this answer for more information.

其他回答

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

"Hello, World!"

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

其他Write-*命令专门用于将文本输出到相关的流中,并具有相应的位置。

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

如果你有一个脚本

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

然后,如果你调用带有重定向输出的脚本,就像你的脚本。Ps1 > out.txt,你将得到屏幕上的test2 test1\ntest3\n在“out.txt”。

请注意,"test3"和Write-Output行总是会在你的文本中追加一个新行,在PowerShell中没有办法停止这一点(也就是说,echo -n在PowerShell的本机命令中是不可能的)。如果你想要echo -n的功能(在Bash中有点基本和简单),请参阅samthebest的答案。

If a batch file runs a PowerShell command, it will most likely capture the Write-Output command. I have had "long discussions" with system administrators about what should be written to the console and what should not. We have now agreed that the only information if the script executed successfully or died has to be Write-Host'ed, and everything that is the script's author might need to know about the execution (what items were updated, what fields were set, et cetera) goes to Write-Output. This way, when you submit a script to the system administrator, he can easily runthescript.ps1 >someredirectedoutput.txt and see on the screen, if everything is OK. Then send the "someredirectedoutput.txt" back to the developers.

您根本无法让PowerShell提交这些讨厌的换行符。没有脚本或cmdlet可以做到这一点。

当然Write-Host完全是胡说八道,因为你不能从它重定向/管道!你只需要自己写:

using System;

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

E.g.

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

您可以在您的场景中使用其中任何一种,因为它们写入默认流(输出和错误)。如果要将输出输送到另一个命令集,则需要使用Write-Output,它最终将在Write-Host中终止。

本文描述了不同的输出选项:PowerShell O用于输出

用什么东西来写入Windows的标准输出是正确的?

实际上,但非常不幸的是,Windows PowerShell和PowerShell Core从v7.2开始,当从外部通过PowerShell的CLI调用时,都将它们所有的6(!)输出流发送到stdout。

See GitHub issue #7989 for a discussion of this problematic behavior, which likely won't get fixed, so as to preserve backward compatibility. In practice, this means that whatever PowerShell stream you send output to will be seen as stdout output by an external caller: E.g., if you run the following from cmd.exe, you'll see no output, because the stdout redirection to NUL applies equally to all PowerShell streams: C:\>powershell -noprofile -command "Write-Error error!" >NUL However - curiously - if you redirect stderr, PowerShell does send its error stream to stderr, so that with 2> you can capture the error-stream output selectively; the following outputs just 'hi' - the success-stream output - while capturing the error-stream output in file err.txt: C:\>powershell -noprofile -command "'hi'; Write-Error error!" 2>err.txt

理想的行为是:

将PowerShell的成功输出流(编号1)发送到标准输出。 将所有其他流的输出发送到stderr,这是唯一的选项,因为在进程之间只存在两个输出流——用于数据的stdout(标准输出),用于错误消息和所有其他类型的消息(如状态信息)的stderr(标准错误),这些消息都不是数据。 建议在您的代码中进行这种区分,即使目前还没有这样做。


在PowerShell:

Write-Host is for display output, and bypasses the success output stream - as such, its output can neither be (directly) captured in a variable nor suppressed nor redirected. Its original intent was simply to create user feedback and create simple, console-based user interfaces (colored output). Due to the prior inability to be captured or redirected, PowerShell version 5 made Write-Host write to the newly introduced information stream (number 6), so since then it is possible to capture and redirect Write-Host output. Write-Error is meant for writing non-terminating errors to the error stream (number 2); conceptually, the error stream is the equivalent of stderr. Write-Output writes to the success [output] stream (number 1), which is conceptually equivalent to stdout; it is the stream to write data (results) to. However, explicit use of Write-Output is rarely needed due to PowerShell's implicit output feature: Output from any command or expression that isn't explicitly captured, suppressed or redirected is automatically sent to the success stream; e.g., Write-Output "Honey, I'm $HOME" and "Honey, I'm $HOME" are equivalent, with the latter not only being more concise, but also faster. See this answer for more information.