【问题标题】:Writing to error stream in Powershell using Write-Error使用 Write-Error 在 Powershell 中写入错误流
【发布时间】:2021-10-30 01:52:14
【问题描述】:

为什么 Powershell 的 Write-Error cmdlet 不适合我?我的输出看起来不像文档中的示例:

PS C:\> Write-Error "This is an error"
Write-Error "This is an error" : This is an error
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

我一直期待类似于Write-Warning 的输出:

PS H:\> Write-Warning "This is a warning"
WARNING: This is a warning

Write-Errorabout_preference_variables 文档中,我认为我不应该看到任何异常?

PS H:\> Get-Help About_Preference_Variables

$ErrorActionPreference
----------------------

...

        PS> $erroractionpreference                      
        Continue        # Display the value of the preference.                

        PS> write-error "Hello, World"                  
                                # Generate a non-terminating error.

        write-error "Hello, World" : Hello, World       
                                # The error message is displayed and
                                  execution continues.

        PS> write-error "Hello, World" -ErrorAction:SilentlyContinue
                                # Use the ErrorAction parameter with a 
                                  value of "SilentlyContinue".
        PS>                                             
                                # The error message is not displayed and
                                  execution continues.

【问题讨论】:

  • 您希望在输出中看到什么?你发布的那个在我看来完全正常。
  • @zespri 我一直在期待类似于 Write-Warning 的内容...我已经编辑了问题以包含一个示例。
  • 您看到的输出是正确的。输出随着 v2.0 IIRC 的变化而变得更加冗长。文档不正确 - 这不是第一次发生。 :-)
  • 你来到这里是因为Write-Error 违反了最小意外原则。

标签: powershell write-error


【解决方案1】:

要获得类似于写警告的输出,您可以这样做:

$Host.UI.WriteErrorLine("This is an error")

(克里斯·西尔斯对此答案的支持)

【讨论】:

  • 太棒了!这对我来说绝对有用。
  • 有趣的是,这写入标准输出,而不是标准错误。 PowerShell ISE 似乎没有回显标准错误,但正常的 PowerShell 提示符会(没有应用特殊格式)。尝试在每个中运行 [System.Console]::Error.WriteLine('test') 看看会发生什么。
  • 不要这样做。 WriteErrorLine 是一种 UI 方法,这就是为什么 Zenexer 说什么都不会重定向到 stderr。请参阅 Keith Hill 的回答和stackoverflow.com/questions/4998173/…
【解决方案2】:

为什么你认为它不起作用?请记住,PowerShell 会区分上述非终止错误和执行throw 'Access denied.' 时遇到的终止错误。非终止错误被写入 stderr 并记录在 $error 集合中,但它们不会停止脚本的处理。当您处理(例如删除或复制)一堆文件时,此功能非常方便。您想知道哪些文件无法处理,但您不希望整个操作在第一个出错的文件上停止。

PowerShell 还为您提供了将非终止错误“转换”为终止错误的选项,例如

Remove-Item c:\file-doesnt-exist -ErrorAction Stop; "Did I get here"

请注意,在这种情况下,执行会停止并且不会在末尾打印出字符串。不带-ErrorAction Stop 试试看,你会看到错误,但你也会看到字符串“我到这里了吗”。

如果你想控制分类信息,你可以像这样使用 -Category 参数:

PS> write-error "foo" -Category 'InvalidResult'
write-error "foo" -Category 'InvalidResult' : foo
    + CategoryInfo          : InvalidResult: (:) [Write-Error], WriteErrorExce..
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException

但是 WriteErrorException 是这个 cmdlet 引发错误的机制(我认为)。有一个 Exception 参数,但我使用它时运气不佳。

【讨论】:

    【解决方案3】:

    我相信您会看到该 cmdlet 的预期输出。您正在输入“拒绝访问”。参数并将其输出到主机,并且最有可能按设计输出到错误流。您可以确认它正在输出到 $Error 变量,并且应该填充您刚刚插入的错误。

    PS C:\> $error.Clear()
    
    PS C:\> Write-Error "access denied"
    
    Write-Error "access denied" : access denied
    
        + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
    
    PS C:\> $error
    
    Write-Error "access denied" : access denied
    
        + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
    

    不过,我可以看出哪里会令人困惑,也许 MSFT 应该将示例错误从“拒绝访问”更改为“Foobar”以清楚起见。

    编辑以解决更多问题: Write-Error 的默认 errorAction 是“继续”,因此要使其表现得像 Write-Warning,您必须添加 -ErrorAction SilentlyContinue。考虑以下示例:

    PS E:\> $error.clear()
    PS E:\> Write-Error 'test'
    Write-Error 'test' : test
        + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
    
    PS E:\> Write-Error 'test2' -ErrorAction silentlycontinue  
    
    PS E:\> $error[1]
    Write-Error 'test' : test
        + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
    
    PS E:\> $error[0]
    Write-Error 'test2' -ErrorAction silentlycontinue : test2
        + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
    

    【讨论】:

    • 为什么会出现“未指定类别信息”WriteErrorException?文档说它是可选的......
    • 它列出未指定的类别信息是因为您正在查看的是标准错误输出,这就是 Write-Error 所做的;当在显示模板的 PS 中引发任何错误时... 示例:'code` PS E:\> lkas 无法识别术语 'lkas' At line:1 char:7 + lkas code 始终列出类别信息;它显示为未指定,因为您没有使用 Write-Error 命令明确指定它。
    • 对不起,我搞砸了那里的迷你降价。请注意,我编辑了我的原始帖子以解决问题的进一步范围。对不起,一团糟:)
    【解决方案4】:

    这里的问题是,我们假设了一种用于打印详细信息、信息、警告和错误消息的模式,并期望 Write- cmdlet 形成一个遵循此模式的集合。

    但是Write-Error 是不同的,并且让人怀疑这种模式是作者有意还是仅仅是程序员的想法。这是 API 设计的亮点。

    写详细

    Write-Verbose cmdlet 将文本写入 PowerShell 中的详细消息流

    写警告

    Write-Warning cmdlet 将警告消息写入 PowerShell 主机。

    写入错误

    Write-Error cmdlet 声明了一个非终止错误。

    哦。它做了一些不同的事情。它“声明”了一个错误。这就像引发一个事件。它不是将文本写入标准错误....

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      • 2017-11-25
      • 2011-06-27
      相关资源
      最近更新 更多