Up to this point in the book, we’ve primarily been relying on PowerShell’s native ability to output tables and lists. As you start to combine commands into more complex scripts, you’ll probably want to gain more precise control over what’s displayed. You may also need to prompt a user for input. In this chapter, you’ll learn how to collect that input and how to display whatever output you might desire.
We want to point out, however, that the contents of this chapter are useful only for scripts that interact with human eyeballs and fingertips. For scripts that run unattended, these aren’t appropriate techniques, because there won’t be a human being around to interact with.
The way PowerShell displays and prompts for information depends on how it’s being run. You see, PowerShell is built as a kind of under-the-hood engine.
What you interact with is called a host application. The command-line console you see when running the PowerShell executable in a terminal application is often called the console host. Another common host is called the integrated host, which is represented as the PowerShell Integrated Console supplied by the PowerShell extension for Visual Studio Code. Other non-Microsoft applications can host the shell’s engine as well. In other words, you, as the user, interact with the hosting application, and it, in turn, passes your commands through to the engine. The hosting application displays the results that the engine produces.
Note Another well-known host is in the PowerShell worker for Azure Functions. Azure Functions is Microsoft Azure’s serverless offering, which is fancy talk for a service that allows you to run an arbitrary PowerShell script in the cloud without managing the underlying environment that script is running in. This host is interesting—because it’s run unattended, there’s no interactive element of this host, unlike the console or integrated host.
Figure 17.1 illustrates the relationship between the engine and the various hosting applications. Each hosting application is responsible for physically displaying any output the engine produces and physically collecting any input the engine requests. That means PowerShell can display output and manage input in different ways.
We want to point out these differences because it can sometimes be confusing to newcomers. Why would one command behave one way in the command-line window but behave differently in, say, Azure Functions? It’s because the hosting application determines the way in which you interact with the shell, not the PowerShell engine. The commands we’re about to show you exhibit slightly different behavior depending on where you run them.
PowerShell’s Read-Host
cmdlet is designed to display a text prompt and then collect text input from the user. Because you saw us use this for the first time in the previous chapter, the syntax may seem familiar:
This example highlights two important facts about the cmdlet:
Whatever the user types is returned as the result of the command (technically, it’s placed into the pipeline, but more on that later).
You’ll often capture the input into a variable, which looks like this:
Try it Now Time to start following along. At this point, you should have a valid computer name in the $computername
variable. Don’t use SERVER-UBUNTU unless that’s the name of the computer you’re working on.
Now that you can collect input, you’ll want some way of displaying output. The Write-Host
cmdlet is one way. It’s not always the best way, but it’s available to you, and it’s important that you understand how it works.
As figure 17.2 illustrates, Write-Host
runs in the pipeline like any other cmdlet, but it doesn’t place anything into the pipeline. Instead, it does two things: writes a record into the “information stream” (don’t worry, we’ll cover this later!) and writes directly to the hosting application’s screen.
Now, because Write-Host
writes directly to the host app’s screen, it’s able to use alternate foreground and background colors through its -ForegroundColor
and -BackgroundColor
command-line parameters. You can see all the available colors by running get-help -command write-host
.
Try it Now Run Get-Help Write-Host
. What colors are available for the ForegroundColor
and BackgroundColor
parameters? Now that we know what colors are available, let’s have a little fun.
Try it Now You’ll want to run this command yourself to see the colorful results.
Note Not every application that hosts PowerShell supports alternate text colors, and not every application supports the full set of colors. When you attempt to set colors in such an application, it will usually ignore any colors it doesn’t like or can’t display. That’s one reason we tend to avoid relying on special colors at all.
The Write-Host
command has a bad reputation because in earlier version of Power-Shell, it didn’t do much. It acted as a mechanism to display information to the user via the console and didn’t muddy any of the streams (yes, we know, we keep talking about these pesky things, and we will get to them, we promise). But starting in PowerShell 5, the Write-Host
command was redesigned. It is now a wrapper for the Write-Information
command, as it needed to be backward compatible. It still will output the text to your screen but will also put your text into the information stream so you can use it later. But Write-Host
does have its limitations and may not always be the correct cmdlet for the job.
For example, you should never use Write-Host
to manually format a table. You can find better ways to produce the output, using techniques that enable PowerShell itself to handle the formatting. We won’t dive into those techniques in this book, because they belong more in the realm of heavy-duty scripting and tool making. However, you can check out Learn PowerShell Scripting in a Month of Lunches by Don Jones and Jeffery Hicks (Manning, 2017) for full coverage of those output techniques.
Write-Host
is also not the best way to produce error messages, warnings, debugging messages, and so on—again, you can find more specific ways to do those things, and we’ll cover those in this chapter. The only time you will really be using Write-Host
is if you want to make a message on the screen with fancy colors in it.
Note We often see people using Write-Host
to display what we call “warm and fuzzy” messages—things like “Now connecting to SERVER2,” and “Testing for folder.” We suggest you use the Write-Verbose
messages instead. The reason we suggest this is because the output being sent the Verbose
stream (which can be suppressed) as opposed to the Information
stream.
Unlike Write-Host
, Write-Output
can send objects into the pipeline. Because it isn’t writing directly to the display, it doesn’t permit you to specify alternative colors or anything. In fact, Write-Output
(or its alias, Write
) isn’t technically designed to display output at all. As we said, it sends objects into the pipeline—it’s the pipeline itself that eventually displays those objects. Figure 17.3 illustrates how this works.
Refer to chapter 11 for a quick review of how objects go from the pipeline to the screen. Let’s look at the basic process:
Write-Output
puts the String
object Hello
into the pipeline.
Because nothing else is in the pipeline, Hello
travels to the end of the pipeline, where Out-Default
always sits.
Out-Host
asks PowerShell’s formatting system to format the object. Because in this example it’s a simple String
, the formatting system returns the text of the string.
The results are similar to what you’d get using Write-Host
, but the object takes a different path to get there. That path is important, because the pipeline could contain other things. For example, consider the following command (which you’re welcome to try):
You don’t see any output from this command, and figure 17.4 illustrates why. Hello
is placed into the pipeline. But before it gets to Out-Default
, it has to pass through Where-Object
, which filters out anything having a Length
property of less than or equal to 10
, which in this case includes our poor Hello
. Our Hello
gets dropped out of the pipeline, and because there’s nothing left in the pipeline for Out-Default
, there’s nothing to pass to Out-Host
, so nothing is displayed. Contrast that command with the following one:
All we’ve done is replace Write-Output
with Write-Host
. This time, Hello
goes directly to the screen, not into the pipeline. Where-Object
has no input and produces no output, so nothing is displayed by Out-Default
and Out-Host
. But because Hello
has been written directly to the screen, we see it anyway.
Write-Output
may seem new, but it turns out you’ve been using it all along. It’s the shell’s default cmdlet. When you tell the shell to do something that isn’t a command, the shell passes whatever you typed to Write-Output
behind the scenes.
PowerShell has a few other ways to produce output. None of these write to the pipeline as Write-Output
does; they work a bit more like Write-Host
. But all of them produce output in a way that can be suppressed.
The shell comes with built-in configuration variables for each of these alternative output methods. When the configuration variable is set to Continue
, the commands we’re about to show you do indeed produce output. When the configuration variable is set to SilentlyContinue
, the associated output command produces nothing. Table 17.1 contains the list of cmdlets.
Note Write-Host
uses Write-Information
under the hood, which means that Write-Host
messages get sent to the information stream in addition to the host application. This gives us the ability to do more with Write-Host
by controlling its behavior with $InformationPreference
, among other things that we can do with PowerShell streams.
Write-Error
works a bit differently because it writes an error to PowerShell’s error stream. PowerShell also has a Write-Progress
cmdlet that can display progress bars, but it works entirely differently. Feel free to read its help for more information and for examples; we don’t cover it in this book.
To use any of these cmdlets, first make sure that its associated configuration variable is set to Continue
. (If it’s set to SilentlyContinue
, which is the default for a couple of them, you won’t see any output at all.) Then use the cmdlet to output a message.
Note Some PowerShell hosting applications may display the output from these cmdlets in a different location. In Azure Functions, for example, debugging text is written to a log in Application Insights (an Azure log-reporting service) instead of a terminal window because in a serverless environment, you’re not looking at a terminal; the PowerShell script is running somewhere up in the cloud. This is done for ease of debugging your scripts and so that you can see the output somewhere.
Note For this lab, you need a computer running the OS of your choice with PowerShell v7 or later.
Write-Host
and Write-Output
can be a bit tricky to work with. See how many of these tasks you can complete, and if you get stuck, it’s okay to peek at the sample answers available at the end of this chapter.
Use Write-Output
to display the result of 100 multiplied by 10.
Use Write-Host
to display the result of 100 multiplied by 10.
Prompt the user to enter a name, and then display that name in yellow text.
Prompt the user to enter a name, and then display that name only if it’s longer than five characters. Do this all with a single PowerShell expression—don’t use a variable.
That’s all for this lab. Because these cmdlets are all straightforward, we want you to spend more time experimenting with them on your own. Be sure to do that—we’ll offer some ideas in section 17.8.
Try it Now After you’ve completed this lab, try completing review lab 3, which you’ll find in the appendix of this book.
Any of these approaches works:
Spend some time getting comfortable with all of the cmdlets in this chapter. Make sure you can display Verbose
output, and accept input. You’ll be using the commands from this chapter often from here on out, so you should read their help files and even jot down quick syntax reminders for future reference.
3.128.78.30