为什么 cmdlet 不应使用控制台 API? [英] Why should cmdlets not use the Console API?

查看:39
本文介绍了为什么 cmdlet 不应使用控制台 API?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 MSDN 强烈鼓励的开发指南:

<块引用>

Cmdlet 不应使用 控制台 API.

这是为什么?

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

一样好用

写主机测试"

众所周知,应该避免Write-Host.当 MSDN 说不要使用控制台 API 时,假设他们暗示我们不应该使用 Write-Host 是否安全,因为它在幕后使用控制台 API?

解决方案

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

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

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

然而,假设存在(称为抽象)host 是安全的,PowerShell 通过自动 $HOST 变量公开它.
然而,主机的功能各不相同,即使直接使用控制台 API,而是使用其 PowerShell 抽象,Write-Host - 见下文.

<小时>

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 实际上可能在不支持用户交互的主机上失败>;参见这个问题.

从 PSv5 开始,Write-Host 可以安全使用,因为它现在写入新引入的、与主机无关的信息流(编号 6) - 参见 Get-Help about_Redirection 和下一部分.

请注意,Write-Host 仍然并且总是在正常 PowerShell output 流的之外生成输出 - 它的输出应该是评论"(对用户的反馈)而不是数据.

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

  • Write-Host"现在有点用词不当,因为它实际上并不直接写入主机em> 了.

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

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

<小时>

Write-HostWrite-Information:

感谢 PetSerAl 在以下方面的帮助.

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

与 PowerShell 处理错误和警告的方式一致,Write-Information显示行为可通过新的 $InformationPreference 首选项变量进行控制/新的通用 -InformationAction cmdlet 参数.
Write-Information默认行为是静音 - $InformationPreference 默认值SilentlyContinue.

请注意,Write-Information 没有直接的格式参数[1],而是通过 -Tags<提供关键字标记/code> 参数[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"实际上如何违反 强烈推荐 cmdlet 开发指南:它应该是标签"(单数).

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

According to the MSDN for Strongly Encouraged Development Guidelines:

Cmdlets should not use the Console API.

Why is this?

If I write [Console]::Write("test"), it works just as well as

Write-Host "test"

EDIT: It's well known that Write-Host should be avoided. When MSDN says to not use the Console API, is it safe to assume that they are implying that we should not use Write-Host either since that uses the Console API behind the scenes?

解决方案

The main reason you shouldn't use console-related functionality is that not all PowerShell host environments are consoles.

While the typical use case is to run PowerShell in a console, PowerShell does not need a console and can cooperate with different kinds of host environments.

Thus, for your code to remain portable, it shouldn't assume the existence of a console.

It is safe, however, to assume the existence of (the abstraction called) host, which PowerShell exposes via the automatic $HOST variable.
The capabilities of hosts vary, however, which has historically created problems even when not using the console API directly, but its PowerShell abstraction, Write-Host - see below.


PowerShell provides a hosting API,

with which the PowerShell runtime can be embedded inside other applications. These applications can then use PowerShell functionality to implement certain operations, including those exposed via the graphical interface.

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

The regular PowerShell console using the Console Window Host (conhost.exe) on Windows is therefore just one implementation of a PowerShell host - the PowerShell ISE is another example, as is the Microsoft Exchange Server management GUI (2007+).


As for Write-Host:

Up to PSv4, as the name suggests, it used to write to the host - which may or may not be a console - so Write-Host could actually fail on hosts that don't support user interaction; see this question.

Starting with PSv5, Write-Host is safe to use, because it now writes to the newly introduced, host-independent information stream (number 6) - see Get-Help about_Redirection and the next section.

Note that Write-Host still does and always has generated output outside of the normal PowerShell output stream - its output is meant to be "commentary" (feedback to the user) rather than data.

While Write-Host is safe to use in PSv5+, it exist for backward compatibility, so instead consider using
Write-Information -InformationAction Continue or using Write-Information with preference variable $InformationPreference set to Continue
, because:

  • "Write-Host" is now a bit of a misnomer, given that it doesn't actually directly write to the host anymore.

  • Write-Host, in the interest of backward compatibility, doesn't integrate with the $InformationPreference preference variable - see below.

  • Write-Host still offers console-inspired formatting parameters (-ForegroundColor, -BackgroundColor), which not all hosts (ultimately) support.


Write-Host vs. Write-Information:

Tip of the hat to PetSerAl for his help with the following.

Write-Information, introduced in PSv5, is the cmdlet that fully integrates with the new, host-independent information stream (number 6).
Notably, you can now redirect and thus capture Write-Information / Write-Host output by using 6>, something that wasn't possible with Write-Host in PSv4-.
Also note that this redirection works even with $InformationPreference's default value, SilentlyContinue, which only governs the display, not the output aspect (only using common parameter -InformationAction Ignore truly suppresses writing to the stream).

In line with how PowerShell handles errors and warnings, the display behavior of Write-Information is controllable via the new $InformationPreference preference variable / the new common -InformationAction cmdlet parameter.
Write-Information's default behavior is to be silent - $InformationPreference defaults to SilentlyContinue.

Note that Write-Information has no direct formatting parameters[1] and instead offers keyword tagging with the -Tags parameter[2] .

By contrast, for backward compatibility, Write-Host effectively behaves like
Write-Information -InformationAction Continue
, i.e., it outputs by default, and the only way to silence it is to use Write-Host -InformationAction Ignore[3] - it does not respect an $InformationPreference value of SilentlyContinue (it does, however, respect the other values, such as Inquire).


[1] PetSerAl points out that you can pass formatting information to Write-Information, but only in an obscure fashion that isn't even documented as of PSv5.1; e.g.:
Write-Information -MessageData ([System.Management.Automation.HostInformationMessage] @{Message='Message'; ForegroundColor='Red'}) -InformationAction Continue

[2] Note how parameter name "Tags" actually violates one of the strongly encouraged cmdlet development guidelines: it should be "Tag" (singular).

[3] PetSerAl explains that this behavior stems from Write-Host passing the PSHOST tag to Cmdlet.WriteInformation behind the scenes.

这篇关于为什么 cmdlet 不应使用控制台 API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆