Why should cmdlets not use the Console API?

后端 未结 2 1513
忘了有多久
忘了有多久 2021-01-13 10:01

According to the MSDN for Strongly Encouraged Development Guidelines:

Cmdlets should not use the Console API.

Why is this?

2条回答
  •  抹茶落季
    2021-01-13 10:32

    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.

提交回复
热议问题