Getting to know Powershell (The basics)

Oh boy, this is going to be a long one, so I hope you have some snacks and some extra Mt. Dew  with you because we’re about to take a look into a lot of different aspects of Powershell. This will probably be a two part post, with the first part being the basics, and the second part being some more advanced functionality of PS.

Why powershell, you ask, why not just use the built in GUI apps to manage your environment? Additionally, why now; powershell has been out for quite a while? Well, my friends, you are right on both counts. You can just as easily use the GUI apps to manage your environment, and Powershell has been out for a while. However, there are an increasing amount of things you simply cannot do in the GUI anymore. For example, go into Exchange Management Console and define a CAS Array object...I’ll wait. Now, go through this list of 200 servers and change a setting for me; I hope you have LOTS more Mt. Dew* with you. That, and Powershell 3.0 came out not long ago, and it’s pretty cool*.

Read on...


Powershell lets you do all that, and a lot more. Microsoft has really been putting a lot of effort into making Powershell more than just a few Command Prompt commands. Sure you can make batch files and VBS scripts to automate some of your workflow, but Powershell is almost a complete programming language in itself. It has much better support for piping commands to other commands, a hugely beneficial and constantly updated help system, support for variables and loops and comparison operators, as well as the ability to format, output, import, export, select and limit your search queries, as well as a slew of other great things. I am a HUGE fan of bash scripts and perl scripts, but the more I work with Powershell, the more I think it has the capability to blow those out of the water.

So, let’s begin with a few important things to know about Powershell.
  1.  It’s case-insensitive. This is important to know. It is case insensitive as much as it can be. That means that Get-Help is the same as get-help or gET-hELP. It also means that your variable $a is the same thing as variable $A.
  1. All commands in powershell are called cmdlets. They are always in the format of Verb-Noun (Get-Help, Set-Something, Read-whatever, Import-Blah). They are also called cmdlets because it’s much easier to google for a cmdlet rather than simply “command”.
  1.  The majority of the time you are working with Objects. This is a good thing, trust me. It’s not making it things difficult for the sake of being difficult. You’ll see more examples of this later on, but the reason that Powershell works with objects is because it’s a lot easier to grab properties of objects than working just with text. As a quick pseudo-example, let’s say that Get-Computer (not a real cmdlet) returns your computer name, ip address, RAM, processor speed, and how long it’s been powered on. If it was a string, you would just get “mycomputer01, 192.168.1.34, 8,2000,123125”. While this is very useful information, if it was a string, to get just the computer name out of that, you would have to write additional code to parse the output and do all kinds of crazy string manipulation. Because it’s an object, and has properties, we can just say that we want to get the computer name...and it gives it to us. Since they are objects, we can also get the output of one cmdlet, and then send it to another (piping, more on this later), and it won’t have to do any crazy conversions since it’s getting a standardized object.
  1.  There’s a lot to it. Don’t get frustrated. I won’t even begin to say that I’m an expert at Powershell (or even close to it), even after using it for a while. There are hundreds of cmdlets, and then there are tons of modules that include even more cmdlets. The idea is to begin to understand how it all works together and then to be able to read other people’s cmdlets or to be able to write your own.
  1.  Powershell is pretty secure. A lot went into the Powershell permissions model. A lot also went into making sure you can’t just run an arbitrary script that might install malware or send your data to some rogue server or format your C:. In the very least, it will prevent Joe LUser from breaking stuff...too much. You can run Powershell against remote computers, and even get a Powershell environment over a web browser. It was made to not only be a scripting framework, but an entire management suite. All data and commands are encrypted, so you’re not just sending usernames and passwords over your network in clear text, either. TLDR: you can safely turn it on (It’s on by default in Server 2012).
  1.  Powershell will do what you tell it to. It will not ask you 40 times to confirm that you want to format c: . If you tell it to do something, for the most part, it will just do it. That said, a lot of cmdlets have two very important “save your bacon”-type parameters that we will get into later: “WhatIf”, and “Confirm”.
  1.  You can use PS on workstations and servers all the way back to Windows XP and Server 2003. Let’s be honest, nobody should be using XP and 2003 anymore; don’t be that guy/girl.
  1.  There are lots of places to get help. The built in help system is fantastic...it’s an actually useful Microsoft help system. I know, right? Then there’s powershell.org, which is a fantastic resource. Also, there are some videos and lessons on microsoftvirtualacademy.com regarding powershell.
  1.  All PS scripts have the extension “.ps1”, but don’t expect to just run those. By default, if you double click on one, it will just open it up in notepad. This is by design, so don’t try to associate .ps1 to powershell.exe. It’s really not recommended, in fact, I’m telling you to not do it. You always do what you’re told, right? Beuller?
  1.  I just need a number 10 to get an even numbered list. Hi, how you doing? Good? Good! If you read this far, congrats, I’m going to get you a puppy*.

Now that we’re done the longest intro of all time, let’s get powershell loaded up. Just in case you don’t have the latest version, make sure to grab The Microsoft .NET Framework 4.0 and then the Windows Management Framework 3.0 (unless you're for some reason going to do some PS practice from an Exchange or SCCM box) from http://www.microsoft.com/en-us/download/details.aspx?id=34595 and get that installed first. If you’re running Windows 8 or Server 2012, then congratulations, you saved yourself a step.

What's new in Powershell 3?

Since I've mentioned that PS has been around a while and we're only now writing a post about it, let's go over a few important things that PS 3.0 gives us to make our lives easier. While it has lots of changes, let's concentrate on those that will be important to the majority of sysadmins.

First, it gives us something called Powershell Web Access. If you are running Server 2012, you can deploy and configure an IIS site that will give you a Powershell environment from any web browser. If you're on a beach with your tablet or phone, if you have internet, you can get a powershell environment for those emergency fixes that your on-site lackey can't figure out.

You can also have persistent sessions. So if you are connected to a remote server over powershell, and your computer dies, that session will still live on the remote computer, and you can then reconnect to it and continue your work.

The help system is also self-updating. In PS3, you can run update-help, and it will go out to the internet and grab the latest help files from Microsoft. This is useful also for modules and cmdlets that you might not have locally. For example, if you want to manage a Domain Controller, but you don't have the AD cmdlets, you can do Get-Help -Online for an AD command, and it will search all cmdlets that Microsoft knows about, whether you have them installed or not.

In PS3, you can delegate commands. You can basically allow certain users or groups to run a certain subset of commands. This is great for Role Based Access Control, and lets you expose some of the more critical cmdlets to certain people without giving them full control.

Additionally, it has better WMI management. Instead of having to use the *-WMI* commands, there is now CIM support, so not only do you have a better way to send WMI commands (there are some limitations with the objects returned with the standard WMI cmdlets that some of you might run into), but also other devices and services that support the Common Information Model.

Lots more cmdlets. This was a given that Microsoft would just let you do more stuff out of the box. There are a bunch more, too many to list here, but they include the new PSSession management, some additional Control Panel cmdlets, the CIM cmdlets, as well as hooks into the Windows Scheduler.

Better tab completion is another feature of PS3, since it not only completes cmdlets, but now it also completes parameters, values, objects, and various other things.

Some Conventions

In order to make this a bit more friendly for the eyes, and to prevent having to say something like "Ok, so type 'get-help' without the quotes", as they do in every tutorial...well...ever, I will color code things.

Things that you should type will be in blue, such as: Get-Help
Things that would be returned from powershell, I'll color code in Red, such as:

PS C:\Users\lkwiecinski> get-help get-service
NAME
    Get-Service

SYNOPSIS
    Gets the services on a local or remote computer.


Things that I want to highlight as important will be in Bold and Italics, such as the PSVersion attribute in the next section.


What version are you running?

Open a Powershell session and type $PSVersionTable and look at the PSVersion attribute.

PS C:\Users\lkwiecinski> $PSVersionTable
Name                           Value
----                           -----
WSManStackVersion              3.0
PSCompatibleVersions           {1.0, 2.0, 3.0}
SerializationVersion           1.1.0.1
BuildVersion                   6.2.9200.16398
PSVersion                      3.0
CLRVersion                     4.0.30319.1008
PSRemotingProtocolVersion      2.2


The Help System

I figure if we're getting to know Powershell, we might as well start with the most useful thing for people starting out with PS: help.

There are a few good things about Powershell 3's help system, the first being that you can always get the latest help files from the internet, another being that there are various levels of detail to the help files, and finally, it supports wildcards.

So let's jump into getting information on various cmdlets. There are two ways to get to the help section of a cmdlet, and those are Get-Help [cmdlet-name] or help [cmdlet-name]. Both of these can be used pretty much interchangeably, but for the sake of being thorough, let's just use get-help.

So to get the help file for Get-ChildItem, we would do Get-Help Get-ChildItem and it will return a bunch of information about the cmdlet Get-Childitem. Upon review, it is not the full help file for that cmdlet, and it only has some general information about it. Microsoft has put in a lot of time updating the help files for all of their cmdlets, so the majority of them have much more robust help information.

As such, there are a few switches we can use in conjunction with Get-Help to get more information.

Get-Help Get-ChildItem -Examples Will give us a bunch of (hopefully useful) examples of the cmdlet Get-ChildItem in action

Get-Help Get-ChildItem -Detailed Will give us more details in the description section for the cmdlet as well as printing out all the examples.

Get-Help Get-ChildItem -Full Will give us even more detail about the cmdlet, it will even tell us what object types the various parameters are, whether they are required or optional, as well as any defaults.

Additionally, there will come a time when we are sending the output of commands to other commands, so Microsoft gives us a handy cmdlet to help us determine object types, and that cmdlet is called Get-Member. However, this is not a cmdlet we just type with some parameters, instead we actually send the output of something into it.

So, for example, if we do a Get-ChildItem, it will return for us the current directory listing as such:
 

Directory: C:\Users\lkwiecinski

 

Mode LastWriteTime Length Name

---- ------------- ------ ----

d-r-- 7/3/2013 9:00 AM Contacts

d-r-- 8/23/2013 9:58 AM Desktop

d-r-- 8/29/2013 2:57 PM Documents

d-r-- 8/28/2013 9:22 AM Downloads

d-r-- 8/1/2013 3:52 PM Favorites

The output of this means something to us, but what does the computer, and more specifically Powershell, see it as? To find out, we can send the output of Get-ChildItem to the Get-Member function like so:

Get-ChildItem | Get-Member

The character in between the two cmdlets is the "pipe" character, and it's usually located right above your Enter key, along with the backslash.  We'll learn more about piping commands in a later section, but if you look at the output of that, you'll see a whole bunch of information (too much to paste here, but you'll see it).

If you look at the output of just Get-ChildItem, you'll see that some of those column names, or properties, show up in the output of Get-Member as...you guessed it: properties.

So what's happening here is that the Get-ChildItem cmdlet (like pretty much any cmdlet) is not just returning text to us, but it's returning an object with properties. Get-Member lets us know what type of object it is returning, and what properties are available for that object.

In short: Get-Member is a type of help system.

Back to good old Get-Help, however. It's useful if you know what cmdlet  you want to use by giving you the description, examples, and other pertinent info about that cmdlet, but what if you aren't quite sure which cmdlet you need, or whether it's get-childitem or get-childitems?

Well, remember when I also mentioned that Get-Help lets you do wildcards? Wildcards let you search through the help system to find useful cmdlets.

Let's say we want to look through the various options we have for dealing with XML files.

Let's do a search for anything XML related by typing Get-Help *xml* and voila, we get a list of all cmdlets and helpfiles about XML. From there we can get more specific and do Get-Help Select-XML for example, as that was one of the returned cmdlets. We can also do leading wildcards, trailing wildcards, and anything in between.

The last useful thing about the help system is that in PS 3.0, we can query the online help system and we can update our local help files as well.

So, let's say that last time we checked, the help file for Select-XML looked incomplete (not that it is..but I don't have an incomplete help file example off the top of my head) and we are POSITIVE that Microsoft has to have updated it by now. Well, we can run

Get-Help Select-XML -Online ... the -Online switch will open up a browser window with the online version of this powershell cmdlet.

We can also update our local help files with a Update-Help and PS will go grab the latest help files from Microsoft.

There is one more useful switch we can use with Get-Help and that is the -ShowWindow switch. Some of the help topics are notoriously detailed, and scrolling through them in the same window as we want to write our powershell script can be quite annoying.

Instead, type Get-Help Select-XML -showwindow and it will open a little popup window with the help topic...and make it searchable.
 

Aliases

Just a quick word about aliases: they exist in Powershell, and they are awesome.

Remember in the previous section how I said that we can use Get-Member to get the properties of an object? Do you really feel like typing out Get-Member all the time? Or when we get to controlling our output, do you want to do Select-Object every time? Of course not!

Aliases, as the name suggests, allow us to make shortened versions of our favorite commands. For example, instead of Get-Member you could just as easily type gm.

Try it: Get-ChildItem | gm
Same thing, right? It's EXACTLY the same thing.

Want to see what other aliases are available? Type: Get-Alias

The Pipeline

Ok, FINALLY we're getting into some actual powershell knowledge. You know where to find cmdlets via the help system, you know how to get their properties, you know that you can use shorthand, so let's get into some detail of how powershell runs and interprets commands, and what this "pipeline" actually means.

But first, I'm going to prepare for my Labor Day BBQ....so stay tuned later on this week for the rest of our powershell deep dive, including all things pipeline, variables, loops, and other programmatic knowledge. 
* Why Mt. Dew? I have no idea, it just seems to be the drink of choice that I see every IT guy drinking. The other option would be a delicious beer, but I highly recommend against making changes to production while drinking. However, beer after breaking something...that’s perfectly fine.

* As long as you don’t try to install it on a box that is running SCCM or Exchange 2010 or older. There is an issue that it will break updates, so if I’d say that you just install PS 3.0 on your workstation so you can have the latest and greatest functionality, but keep PS 2.0 on servers that run SCCM or Exchange.  I never said it was perfect...

* I’m not going to really get you a puppy. We’ll have to see about that. However, feel free to email me (lkwiecinski at anexinet dot com) pictures of cute puppies. I might post a few cute ones here.

Labels: