PowerShell has been around for over seven years now. While the basics are easy, the more useful functionality is not easy to learn. Therefore, I came to my own PowerShell self-discovery several months back and since then have used it for all kinds of tasks: storing my passwords, managing my personal computers to reduce my use of the mouse, configuring remote computers, provisioning cloud infrastructures (on AWS and Azure), writing deployment scripts, and coding my own PowerShell command line tools.
So what is PowerShell?
It is a scripting language that runs inside a shell on the Microsoft platform. Significantly, it differs from DOS and scripting languages on other platforms in that it is .Net based, NOT text-based. In other words, in other popular shells, all input and output is in the form of text. This means the text must be manipulated in order to be of use as the input to commands or the output from commands. In PowerShell, while text (strings) are certainly supported, input and output is represented as .Net objects. This means that input and output does not require text manipulation and the user inherits all of the power of objects.
A couple more definitions:
In general, a scripting language is best suited for writing small blocks of code. It is high level, meaning it greatly abstracts the underlying hardware, making scripting good for rapidly writing functional programs to perform very specific tasks, sometimes at the expense of performance or flexibility.
Advanced Aside: Note that PowerShell is Turing Compete.
A shell, or command line interface, is an interpreter that hosts a scripting language. In other words, rather than compiling code into binary, a shell accepts scripts on the fly and executes them into meaningful actions.
Microsoft decided to call PowerShell commands cmdlets (pronounced command-lets). Importantly, by convention, cmdlets are verb-noun pairs. Actual examples include:
Modern Windows ships with two PowerShell shells, which Microsoft calls “Hosts.” However, vendors are able to provide additional shells:
- PowerShell: The default host
- PowerISE (Integrated Scripting environments): A multi-tab environment for writing scripts and performing basic debugging with break points (NOTE: scripts can actually be written in any text editor as well as the standard PowerShell host).
The easiest way to launch PowerShell is just to start it from your Windows Programs menu.
The Three Key Commands
The following three cmdlets are all you need to know to get started using PowerShell:
Get-Help (or just type ‘help’): Provides basic and extended help and syntax for any given PowerShell cmdlet. For example, at the PowerShell prompt, type:
Now trying typing this:
Get-Help Get-Help -Full Notice this time PowerShell includes examples in addition to the basic usage.
Advanced Aside: adding -Full is an example of something PowerShell calls a switch.
NOTE: the first time you run help you may be promoted to update the help content. This is because PowerShell is able to reach out over the Internet to download help content. In fact, the clean install may not even ship with the help files installed until you run this download for the first time.
Get-Member: Lists the methods and properties available on an object. Remember, PowerShell input and output are .Net objects, not text. Therefore, the input and output have methods and properties, just like all .Net objects do. For example, type:
7 | Get-Member. PowerShell tells you that “7” is an int (System.Int32) and lists the methods a .Net developer would expect to see on ints, such as ToString and GetType.
Advanced Aside: the first part of this command, “7 | ” is called a pipe and without getting to detailed tells PowerShell to apply the Get-Member command to the number 7.
Get-Command: Lists every cmdlet and function currently available to call in the PowerShell host (for now, ignore the difference between a function and cmdlet and think of them as the same). You can also narrow down the available cmdlets to list. For example, if you think the verb in the verb-noun cmdlet pair starts with “Get” you can type
Note that PowerShell is case insensitive, “get-*” is the same as “Get-*” or “GET-*”
Advanced Aside: I was very careful to state that Get-Command by itself lists the cmdlets PowerShell currently knows about. That is because it is possible to add more cmdlets into the PowerShell host’s scope.
As I demonstrated above, PowerShell also accepts wildcards for parameter values and as part of its Intellisense, when you are selecting cmdlets in the host or ISE. Type for example
Get-H* and then press <tab>. Watch how PowerShell cycles through the list of available cmdlets each time you press <tab>.
Advanced Aside: There are other ways of doing this too. My first instinct was to pipe the result of Get-Process to a where clause. But I haven’t shown where clauses in this post. Fortunately, there are many ways to do the same thing in PowerShell, though they may not all have the same performance characteristics if you are running long running scripts, especially on remote computers.
Pipes and More
By way of demonstrating another important feature, try typing this:
Get-Service | More into your PowerShell host (note it may not work in the ISE). This lists all Windows services in your computer but only displays enough to fill the current screen (so you don’t need the scroll bar). To continue through the list, hit the
<space> bar. The | is called the pipe and applies the output of the stuff to the left of the pipe as input to the stuff to the right of the pipe. I showed another example of this earlier when I did this
7 | Get-Member.
Cmdlets vs Scripting
In this post I have only demonstrated typing simple cmdlets or functions on the host. But PowerShell provides a rich syntax for writing scripts with standard programming constructs like loops, decisions, Boolean logic, etc.
Basic Cmdlet Example
I want to end this post by showing how you might use your newly acquired skills to list all running processes on your computer that start with the letter “S.” Let’s say you suspect their might be an out of the box PowerShell cmdlet for this. You already know that all cmdlets follow a verb-noun pair. So you might think the cmdlet contains the word “process.” Therefore, type this in your PowerShell host:
*process* and press <tab>. Keep tabbing through…. ah, Get-Process looks promising. Let’s see what it does. Type
Get-Help Get-Process. Looks good! The resulting help even shows a syntax with the parameter – Name. And you should be thinking to yourself, “Adam said I can include wildcards in my parameter values.” So now you type
Get-Process -Name "S*" and watch the magic happen!
So I’ve come to the end of this, the first blog post I’ve ever written. As time rolls on, I expect to expound on more features of PowerShell. If you’re really desperate to learn it in depth, now, however, then I strongly recommend this book: Windows PowerShell Cookbook.