【问题标题】:Why should cmdlets not use the Console API?为什么 cmdlet 不应该使用控制台 API?
【发布时间】:2017-04-20 03:27:35
【问题描述】:

根据MSDN for Strongly Encouraged Development Guidelines

Cmdlet 不应使用 Console API。

这是为什么?

如果我写[Console]::Write("test"),它的效果和

Write-Host "test"

编辑: 众所周知,应该避免使用Write-Host。当 MSDN 说不使用控制台 API 时,是否可以假设他们暗示我们不应该使用 Write-Host,因为它在后台使用控制台 API?

【问题讨论】:

    标签: powershell


    【解决方案1】:

    您不应该使用与控制台相关的功能的主要原因是并非所有 PowerShell 主机环境都是控制台

    虽然典型用例是在控制台中运行 PowerShell,但 PowerShell 不需要控制台并且可以与不同类型的主机环境协作。

    因此,为了让您的代码保持可移植性,它不应该假定存在 控制台

    但是,假设存在(称为抽象)host 是安全的,PowerShell 通过自动 $HOST 变量公开它。
    但是,主机的功能各不相同,即使直接使用控制台 API,而是使用它的 PowerShell 抽象 Write-Host,这在历史上也会产生问题 - 见下文。 p>


    PowerShell 提供了一个托管 API

    PowerShell 运行时可以嵌入到其他应用程序中。然后,这些应用程序可以使用 PowerShell 功能来实现某些操作,包括那些通过图形界面公开的操作。

    https://en.wikipedia.org/wiki/PowerShell

    在 Windows 上使用 Console Window Host (conhost.exe) 的常规 PowerShell 控制台因此只是一个实现PowerShell 主机 - PowerShell ISE 是另一个示例,Microsoft Exchange Server 管理 GUI (2007+) 也是如此。


    至于Write-Host

    直到 PSv4,顾名思义,它用于写入 主机 - 可能是也可能不是控制台 em> - 所以 Write-Host 实际上可能在不支持用户交互的主机上失败;见this question

    从 PSv5 开始,Write-Host 可以安全使用,因为它现在写入新引入的独立于主机的信息流(编号 6) - 请参阅 Get-Help about_Redirection 和下一个部分。

    请注意,Write-Host 仍然在正常 PowerShell output 流的outside 生成输出 - 它的输出是“评论”(反馈给用户)而不是数据

    虽然Write-Host 在PSv5+ 中使用是安全,但它的存在是为了向后兼容,因此请考虑使用
    Write-Information -InformationAction Continue 或@ 987654339@ 首选项变量$InformationPreference 设置为Continue
    ,因为:

    • “Write-Host”现在有点用词不当,因为它实际上并没有直接写入 host em> 了。

    • Write-Host,为了向后兼容,不与 $InformationPreference 首选项变量集成 - 见下文。

    • Write-Host 仍提供受控制台启发的格式化参数(-ForegroundColor-BackgroundColor),并非所有主机(最终)都支持。


    Write-HostWrite-Information

    PetSerAl 致敬,感谢他在以下方面的帮助。

    Write-Information,在 PSv5 中引入,是与新的、独立于主机的信息流(编号 6)完全集成的 cmdlet。
    值得注意的是,您现在可以通过使用 6>重定向并捕获Write-Information/Write-Host输出,这是不可能的在 PSv4 中使用 Write-Host-.
    另请注意,即使使用$InformationPreference 的默认值SilentlyContinue,此重定向也有效,它只控制显示,而不是输出 方面(仅使用公共参数@ 987654357@ 真正抑制写入 到流)。

    根据 PowerShell 处理错误和警告的方式,Write-Information显示 行为可通过新的 $InformationPreference 首选项变量/新的通用 -InformationAction cmdlet 参数进行控制。
    Write-Information默认 行为是 silent - $InformationPreference 默认为 SilentlyContinue

    请注意,Write-Information 没有直接格式参数[1],而是提供带有-Tags 参数的关键字标记[2] .

    相比之下,为了向后兼容,Write-Host 的行为实际上类似于
    Write-Information -InformationAction Continue
    ,即它默认输出,而唯一的方法是使用Write-Host -InformationAction Ignore[3] - 它确实尊重SilentlyContinue$InformationPreference 值(但是,它尊重其他值,例如Inquire)。


    [1] PetSerAl 指出您可以将格式信息传递给Write-Information,但只能以一种从 PSv5.1 开始甚至没有记录的晦涩方式;例如:
    Write-Information -MessageData ([System.Management.Automation.HostInformationMessage] @{Message='Message'; ForegroundColor='Red'}) -InformationAction Continue

    [2] 注意参数名称“Tags”实际上违反了strongly encouraged cmdlet development guidelines 之一:它应该是“Tag”(单数)。

    [3] PetSerAl 解释说,这种行为源于Write-Host 在幕后将PSHOST 标签传递给Cmdlet.WriteInformation

    【讨论】:

      【解决方案2】:

      [Console]::WriteWrite-Hostbasically the same。他们都向控制台写了一条消息,可以在屏幕上看到。

      不鼓励这样做的基本原因是它破坏了工作流程。 Write-Host cmdlet 的输出无法通过管道传输或进一步使用。现在,如果脚本在没有图形输出或类似约束的机器上运行,则该命令将丢失。

      根据thisthis 线程,因此您应该使用Write-Output,它将输出消息发送到可以进一步使用的管道。此外,如果您的消息旨在表示错误,您可以使用异常。

      【讨论】:

      • 您是说 [Console]::Write 和 Write-Host 都破坏了工作流程并且无法进一步传输?没关系,我感兴趣的是为什么我们不应该使用 [Console]::Write 如果它与 Write-Host 做同样的事情。
      • 据我所知,消息是:两者都不用。
      • MSDN 文章并没有说不使用 Write-Host,而是说不使用控制台 API。你认为既然 Write-Host 在幕后使用控制台 API,他们是否暗示我们也不应该使用它?
      • 你说得对,这有点含糊。我的思路是,如果你不应该使用[console]::write,而[console]::writeWrite-Host基本相同,所以不要同时使用。但这是你要质疑的第二个假设,我知道......这是我提到另一个 SO 答案的地方,但这远不能确定;-)
      • [Console]::WriteWrite-Host 以前基本相同,直到 PowerShell v4。由于并非所有 PowerShell 主机都是控制台,Write-Host曾经可能会破坏您的代码。从 PowerShell v5 开始,Write-Host 可以安全地用于所有主机,但最好使用WriteInformation -InformationAction Continue
      猜你喜欢
      • 2017-03-17
      • 1970-01-01
      • 1970-01-01
      • 2010-10-16
      • 2014-04-13
      • 2017-02-07
      • 2021-09-23
      • 2022-01-15
      • 1970-01-01
      相关资源
      最近更新 更多