Let’s take a look at the kind of commands you can send to PowerShell. Always remember: it does not matter how you send these commands to PowerShell – whether you use the PowerShell Console, the ISE Editor, or any other PowerShell host. Anything you see here works in any PowerShell host because they all talk to the same PowerShell.
You just need to actually read these messages. Often, they are pretty good at explaining what’s wrong. Admittedly, they are a bit tight and technical – because IT people’s hair is frequently on fire, and they just don’t have the time to read through poetry.
Now that we have this out of the way, let’s start to make friends with PowerShell:
PowerShell understands numbers and operators (after all, it lives inside a computer). You don’t need a special output command to see results. Just enter your calculation:
- For input, PowerShell always expects the dot to specify decimals. That’s good, so PowerShell code does not need to be adjusted to run in different cultures.
- For output, PowerShell honors regional settings. In Germany, for example, the decimal is represented by a comma.
- Code in parenthesis is executed first, and Powershell continues with the result – just like in math.
- There is no need for a special output command like “echo” or “print”: anything you “leave behind” will oxidize to text and appear in the console.
Remember PowerShell is for IT people. PowerShell always works with decimals, but IT people don’t. They love to occasionally toss in hexadecimal values, and work with units like “MB” or “PB”. That’s why PowerShell supports a number of shortcuts so people can continue their habits:
- Use the prefix 0x to indicate a hexadecimal value
- Use the units KB, MB, GB, TB, and PB, but do not place spaces inbetween the number and the unit. They must be one expression.
- Use the operator “..” to create ranges of numbers. It supports whole numbers only, and nothing else (no letters, for example).
- The “..” operator uses two dots, no more or less. When you add more dots, PowerShell behaves differently:
Can you guess what happend here? No red error message, so PowerShell is feeling just fine with your input. Should you be slightly confused, here’s the clue:
The “..” operator consists of two dots, not three, so there’s one left over. The left over dot is treated as decimal, and PowerShell happily creates a range of numbers between 1 and 0.3. Since it only supports whole numbers, it rounds the second number and in the end produces a number range between 1 and 0. PowerShell tries best to make sense of what you enter.
Anything PowerShell outputs into the console can also be assigned to a variable. Variables always start with “$”, followed by a name. They work like data containers and can store anything that you might want to reuse later.
So to reuse variable content, simply output the variable. More often, variable content is used to post-process information. If you include a variable in double-quotes.
You are not the only one using variables. Both PowerShell and Windows use them, too. So there are many predefined variables that you can use.
To see the predefined PowerShell variables, open a fresh new PowerShell, and try this:
Get-Variable dumps all variables created in PowerShell, so when you define some own variables, they will also appear in this list.
You can even open an extra window with full variable descriptions (we’ll cover the commands in this line later):
Windows uses a separate drive for its variables. They are called “Environment Variables”, and the drive name is “env:”:
Single and Double Quotes
When you put text into single quotes, PowerShell won’t touch it. When you use double-quotes, any variable inside of your text is automatically replaced with its content.
In the ISE Editor (and in the PowerShell Console with PSReadLine loaded), color coding shows the difference. The color for variables inside your double-quoted strings change.
Applications are executables, typically with file extension “.exe”. PowerShell happily runs these when you enter their name. Applications with an own window (like notepad or regedit) are launched in “hit-and-run” mode: PowerShell fires up the application and immediately returns.
Console applications, in contrast, have no own window. They share the console with PowerShell, so PowerShell waits for the console application to complete. All results from such commands are dumped to the PowerShell Console window.
Receiving Visible Results
If a console application returns visible information, and PowerShell does not care about it, the information is dumped to the console. PowerShell can also decide to take that information, and do things with it. You can use the pipeline operator (“|”) to send the information to another command:
Or you can put the application in parenthesis (remember: anything in parenthesis is executed first, and then PowerShell continues with the results), and use operators to filter the results.
You can assign the output to a variable, too, and later reuse the value in that variable:
There is a special variable called $null which has a memory deficit: it always forgets what you assign to it. It works like a garbage can, so if a command outputs things that you don’t care about, assign it to $null. Here is an example:
Which raises the question why you would want to ping someone, just to discard the result. You’ll find the answer when you look at invisible results (see below).
Receiving Invisible Results
Console applications have another invisible output channel, the “Error Level”. It’s a numeric value, and the author of a console application can return extra information this way, for example success or failure status, or an error number. PowerShell receives this information in the variable $LASTEXITCODE.
Here is the previous example which did not seem to make much sense at first. With $LASTEXITCODE, it works a lot better:
The application ping.exe returns 0 when it received at least one response, else 1. $LASTEXITCODE reveals this invisible result and can be used to check for a result from ping. Note however that ping.exe treats anything as answer, even if your router tells you that some error condition was encountered.
PowerShell has commands of its own. They are called “Cmdlets” (speak: “Commandlets”).
Their name always consists of two parts: verb and noun. That makes cmdlet names sometimes awkward but always very descriptive. And that’s great, because there is a natural systematic organization of cmdlets. It makes it easier to find the right one.
The verbs are regulated by PowerShell, and the cmdlet Get-Verb dumps the list of legal verbs:
Once you know the verbs and what they do, it’s easy to find cmdlets. And to pick the right one. For example, the verb “Get” always gets information. This verb identifies cmdlets that are friendly and will never change or damage things. These cmdlets are perfect candidates to play with PowerShell.
Discovering New Commands (and Cmdlets)
One of the most important skills for PowerShellers is to find and reuse solutions. After all, PowerShell is about automation, and automation is driven by laziness which in turn relates to efficiency.
The most important cmdlet for you to remember is called Get-Command, because it gets you all the other commands. Cmdlets are just one type of command. Applications are another type of command. And Get-Command can always identify unknown commands and their type for you:
As you see, PowerShell hosts a huge zoo of command types. The column CommandType lists the type of a command, and to your slight surprise, you may discover that Get-Printer is not a cmdlet but a function. From your perspective they both are the same. It’s the way how these commands were created that differs: a cmdlet is binary and compiled, and you cannot easily change it or check how it does its job. Functions are plain PowerShell code that can be viewed, and even changed.
What’s more important is that both cmdlets and functions typically ship as part of a PowerShell Module. The column Source reports the name of that module. You’ll learn more about this later, but you can already feel that PowerShell commands are extensible: the more modules you have, the more commands you have.
Finding New Commands
Get-Command can also search and find commands for you. Let’s play safe, and look for all cmdlets with the verb Get (since they won’t change anything on your system).
When you enter this command in the ISE Editor (or the PowerShell Console with PSReadLine installed), colors show that it has more than one part: the command is followed by a parameter name and then an argument. That’s the PowerShell way of talking to a cmdlet, and telling the cmdlet what you want.
- Parameter: always start with a hyphen (“-“). Each cmdlet defines what parameters it offers. In the ISE Editor, parameters show in IntelliSense menus. In the console, after a cmdlet name enter a space, then a “-“, and then press TAB as often as you want to see all parameters.
- Argument: this is “your” input that you want to send to a particular parameter.
Get-Command is not the only one that can find cmdlets for you. Try running Show-Command:
It opens a window where you can see all currently known cmdlets (and functions). You can filter by name, and on top in a combo box even by module.
Once you select a command in its list, the dialog shows all the parameters as form fields, so you can fill out the parameters like an order form. Once you’re done, click “Run” to run the command, or “Copy” to copy the code to the clipboard.
There are also a bunch of common parameters (that are shared by any cmdlet). If you’d like to get help (and possibly sample code) for a cmdlet, use “-?”:
If you’re online, visit the most current online help version:
And if you’re in the ISE Editor, click any cmdlet anywhere in your console or editor pane, make sure you did not make a selection, then press F1. Now help shows in its own searchable help window so you can move it to a second screen for reference. When you secretly look into the ISE console pane, you’ll discover that pressing F1 just typed in a command line for you, for example:
So it basically is the cmdlet Get-Help and its parameter -ShowWindow that opens the extra help window. Once you know that, you can run the command from the PowerShell Console, too. The console just does not support the lazy F1 functionality.
The truth is: any cmdlet is just a chunk of .NET code with an easy to use interface. So when you have played with the cmdlets in the previous section, you actually executed a bunch of .NET code without knowing. That’s great because PowerShell is about getting results fast.
If you are intrigued to be a programmer, or just curious to learn more, then you can always execute .NET code directly, anywhere. We’ll only scratch this here and come back to it later, but these examples should help anyone with .NET background to get a first idea: