One of the most heavily touted new features of Windows Vista, Windows 2008 and Windows 7 has been the introduction of PowerShell, the new command line scripting environment Microsoft developed to help make life easier for Windows Administrators. But there's a problem. Windows Administrators around the Internet are looking at PowerShell with this deer-in-the-headlights look. They're afraid of it, because it's new, it's completely different from anything Windows has had before, and everyone around them is saying it's the best thing since...well...Active Directory.
I, like most Windows Administrators with little to no scripting experience, approached PowerShell with that icky-fingers feeling one gets when cleaning dead cockroaches off the floor. Scripting, for me, was always one of those things that just made me shiver and made my brain want to crawl out the back of my head and hide under a box in the corner.
Then I got a new job and the first thing my new boss asked me to do was solve a number of problems that could only be done with PowerShell. So I had to learn and I had to do it fast. I looked around for some good resources and found plenty. The sad thing was that they all seemed to be written by and for people who had a lot more experience than I did. So I just decided to use my talent for figuring things out on my own and dove in.
Before we get into the groove and start doing things with PowerShell, it's important to understand how it was developed. Almost all system administrators know that a lot of the work they do is very repetitive. You have to add users, remove users, create and delete mailboxes, and do all sorts of mundane tasks that don't take a great deal of skill to do. Well, at least, if you're doing it the hard way.
The idea behind scripting is to do more in less time. Without a script, adding 100 users to an Active Directory environment can take hours. With a script, you can do the same task in just the time it takes to write the script and run it.
Ever since the days of Windows 2000, scripting was limited to somewhat long and occasionally complex scripts written in a cut down version of Visual Basic called VBScript. The only other option available to system administrators was Batch Scripting. While VBScript was a fairly functional programming language capable of doing pretty much anything you wanted to do in an environment, Batch Scripts were limited to pre-built commands that were supplied by Microsoft or picked up from third party developers. However, Batch Scripting had something that VBScript didn't, a very shallow learning curve. Once you learned a few of the commands you needed to develop Batch Scripts, you could make great use of it.
VBScript, on the other hand, required knowledge of some complex and often very unintuitive programming concepts. It took a lot longer to learn VBScript, which meant that a lot of time inside and outside of work had to be devoted to learning the language. In addition, writing workable VBScript code required a lot of troubleshooting and effort, and many times it takes longer to write the script than it takes to perform the task manually, so VBScript is typically limited to repetitive tasks that have to be done very often. In addition, there are numerous security concerns surrounding VBScript.
Because of the chasm that existed between Batch Scripting and VBScript, a lot of systems administrators complained about the lack of a truly functional scripting language in Windows that was easy to use and learn. As a result, Microsoft decided to develop an entirely new scripting system that took the functionality of VBScript and smashed it together with the softer learning curve associated with Batch scripting as a way to replace VBScript and . The result is PowerShell.
PowerShell is, in essence, a Batch Scripting environment that rides on top of Microsoft's .NET Framework and is a fully-functional programming language. As you get deeper into the world of PowerShell, you will discover that it is almost infinitely flexible. Tasks that could have taken hours or days just to script can be done with a few simple commands. In fact, most administrative tasks can be done with a single, small script file that consists of fewer than 10 lines of code. Some things, like importing 100 users as mentioned earlier, can be done with a simple two line script. The end result is that tasks that used to take hours can now be done in minutes. Of course, before you can really get anything out of PowerShell, you have to start learning it. Luckily, it isn't hard to learn. You just have to hold your breath, get ready, and dive right in the way I did.
Diving In Head First
The biggest mistake that beginners make with PowerShell is to approach it like every other scripting language. You know, starting out with cute little scripts that scream "Hello World" on the monitor and little else. But what so many people who just give up on PowerShell realize is that it does not have to be approached as a scripting language. In fact, if you really want to avoid the scripting heeby-jeebies altogether, PowerShell can be treated just like our old friend the command prompt. And you'll still be able to do a lot of really powerful administration things with it. So the very first thing you want to learn about PowerShell is the cmdlet.
Okay, actually, the first thing you need to know is how to start PowerShell. There are a few ways, but the simplest is probably just typing powershell
at the command prompt or in the Run box. The other way to start powershell is to double-click a .ps1 file, which is just an ordinary text file containing powershell statements.
But getting back to it, cmdlets (Commandlets, if you wish), are self contained scripts that require only that they be called like a command in the command shell. For instance, if you want to see the date, just type get-date. Or if you want to see which services are running and which aren't, type get-service. To get a list of cmdlets that you can use in PowerShell, type get-command (Or go here: http://technet.microsoft.com/en-us/magazine/ff714569.aspx where you can get a list of commands for PowerShell 2, which is being distributed by Microsoft now). I should note at this point that there are additional cmdlets available for use with Active Directory and Exchange, but I won't go into depth with those.
Getting cmdlets to Work Together
While it might be nice to be able to view the date or services in PowerShell, those really aren't things you can't do in good old cmd. The real power of PowerShell is its ability to basically squish cmdlets together to do different things. I've heard it compared to the old erector sets that kids used to play with before video games started melting the brains of yungins world wide. How does this work? Through a PowerShell feature called Command Pipelining. By using the pipe ("|") character, we can have one cmdlet take input from another cmdlet to complete complex tasks with a single command.
Let's start with a for-instance. For some very odd reason you wanted to start every single service on a specific computer. Normally, you'd have to open the services.msc snapin and go nuts with the right clicking. With PowerShell, you need only smush together two cmdlets, get-service and start-service, by typing the following:
With this command, you will instruct the computer to start every single service on the machine, because the piping function of the | character will pass the names of all the services that exist to the start-service cmdlet.
I'm not going to tell you that starting every service on a computer is a good idea. This is just an example of what you can do with PowerShell. I didn't say it was useful. I should also mention that (a) not every service on a computer will start with this, because some services won't start unless certain other requirements are met, and (b) services already started will be processed, too. More advanced features of PowerShell and get-service will let you filter this command so it only starts services that aren't working. If you are interested, see Example 5 of help get-services -examples. I will likely cover these advanced features in later articles, but it isn't important right now.
Two Steps Forward, One Step Back, and Two More Steps Forward
Going back a bit, remember one of those little semi-useless cmdlets I told you about earlier, get-date?. Being able to see the date and time is great and all. But how about what time it is down to the nanosecond and beyond? How about how many days we are into the year? There's a way to do that, because each cmdlet that returns data only shows a small amount of the data that it actually captures. Another cmdlet, called format-list (or fl for short) will pull and display all the data that a cmdlet retrieves in a formatted list on the screen. Interestingly, format-list does absolutely nothing if it isn't piped with the "|" character - you can't format "nothing". So, let's try something. Just for giggles, lets squish together that dinky little get-date cmdlet with format-list and see what happens:
Now that's a lot more information than just get-date. And the cool thing is, in more advanced PowerShell scripts, you can use each and every line of that output to do something. This is because each line of the format-list output represents an object property that can be used, modified, squished, molded, and prodded through different functions and techniques. But that's getting into the advanced world of PowerShell, and we're not heading there just yet.
The Real World: PowerShell
Now that we're getting our feet wet, how about a little exercise? Let's say that you have a list of user names in a CSV (or Comma Seperated Values) file. Kinda like this one:
Note: Copy to Notepad and save, or download this: names.csv
If you save that file anywhere on your hard drive (remember where you save it!) you can use it to do some pretty interesting stuff.
But before that, I'll need to introduce you to a couple of additional cmdlets. First is import-csv. Import-csv is one of the more important cmdlets you'll learn about because it's used to automate a lot of administrative tasks in some of the more complex scripts. So let's run it using that little CSV up there. Enter this command:
Your output should look similar to this image: What the import-csv command did here was take the first line and use that as a Descriptor for all the lines below it. If we run the same command on a CSV file that has a comma between all the fields on each line, like this file:
FirstName, LastNameBob, HenryHenry, HenryJoe, Henry
We get a different result: I won't try to overload your brain by going into why that happens in this guide. For now, just stick with the first CSV file, and let's do something with it using another cmdlet, md.
Md isn't so much a cmdlet as it is an alias for a function. An Alias is another, usually shorter, way to call a cmdlet in PowerShell, and a Function is basically a PowerShell script that has been defined for use in other scripts. In this case, md is an alias of the mkdir function. You don't need to know what mkdir does in depth, suffice it to say that it creates a new folder on a drive.
So now we have two cmdlets, a CSV file, and a dream: We want to make new folders using that CSV file. For this exercise, just create a new folder to work in so we don't clutter everything on your computer up (unless you like clutter) and move the CSV file into it. Hop into PowerShell and navigate to that folder just like you would in the command prompt, then run the following command:
You should see the following:
If that's what you saw, congratulations, you've just created three directories from a simple CSV file. You would use something like this if you wanted to create a bunch of folders to assign home folders for users on a file server. If you want to check on this, open My Computer and navigate to the folder where we did all this. You'll see the Bob, Henry, and Joe folders just sitting there hanging out. Now, imagine if that CSV file had 100 names in it (or build a CSV with a hundred names in it and try it out), and you can see where PowerShell can really help cut down on the amount of work we have to do.
Now that you're in the shallow end of the vast ocean that is PowerShell, you can make your choices about where to go from here. You can stick with the simple commands and get a lot of work done really easilly, or you can choose start heading for open water and learn how to really unlock the Power of PowerShell.
But don't worry, you don't have to abandon the floaties yet, each cmdlet has its own help page to help you get familiar with it. If you want to learn more about a specific cmdlet, type get-help <cmdlet> at the PowerShell prompt, get-help <cmdlet> -examples will give you some usage examples and scenarios to help learn syntax a little better, and get-help <cmdlet> -full will give you everything you ever wanted to know about a specific cmdlet. Or at least, everything Microsoft wants you to know. In addition, Microsoft has published full documentation on each cmdlet on Technet; take a look at the additional references or just do a search for PowerShell cmdlets.
PowerShell can be extremely powerful and cut your workload down by a great deal if you can learn to use it. Its capabilities range anywhere from the fairly simple (as I've shown) to the very complex (imagine setting up an entire AD domain to work the way you want right out of the box with a single script). The end result is that PowerShell is definitely worth putting some of your time into learning. It will make your job easier, your bosses happier, and your clients more satisfied with your work. And you might actually have enough time to talk to your significant other. Or even *get* a significant other. Who knows?