Click to Rate and Give Feedback
Tips
Discover how you can service Windows images and prepare Windows PE images with the new Deployment Image Servicing and Management (DISM) command line tool available with Windows 7. ...

Read more!

The Recovery Console has been deprecated in Windows Vista, so what happened to all those commands? Here's how you can access some of those familiar tools. ...

Read more!

To make replication go smoothly, you need to do a bit of planning, which involves selecting a specific replication model. Here's an overview of the common replication models you will likely choose from. ...

Read more!

Learn how to install Hyper-V on both full and Server Core installations of Windows Server 2008. ...

Read more!

Learn how you can use Windows PowerShell 2.0 to gather system stability and reliability data from remote computers running Windows 7. ...

Read more!

Related Articles

Ever wish Windows PowerShell would launch with a work environment tailored to your needs? Don Jones demonstrates how you can use profiles to customize the Windows PowerShell shell.

Don Jones

TechNet Magazine October 2008

...

Read more!

In the past few installments of the Windows PowerShell column, Don Jones has been demonstrating how to develop a Windows PowerShell-based inventory tool. In this installment, Don brings it all together into a very powerful, full-featured tool, and offers some guidance on customizing the tool for your own needs.

Don Jones

TechNet Magazine February 2009

...

Read more!

The Scripting Guys discuss Socrates and revisit the topic of querying an XML file . This time, however, the XML file is structured so that rather than using child nodes, additional property values are configured as attributes.

The Microsoft Scripting Guys

TechNet Magazine October 2008

...

Read more!

Don Jones kicks off a four part series that will look at how you can use Windows PowerShell to create a real-world user provisioning script.

Don Jones

TechNet Magazine March 2009

...

Read more!

Following up on the November installment of his Windows PowerShell column, Don Jones demonstrates an even better inventorying tool and demonstrates a sound process for building your own custom Windows PowerShell functions.

Don Jones

TechNet Magazine December 2008

...

Read more!

Also by this Author

Don Jones concludes his four-part series on automating user provision with Windows PowerShell. In this final edition, Don discusses adding users to domain groups and modifying directory attributes.

Don Jones

TechNet Magazine June 2009

...

Read more!

Windows PowerShell 2.0 is in the works and the latest CTP provides some great new capabilities. Here’s a look at remoting—one of the most exciting new features you'll find in Windows PowerShell 2.0 CTP2.

Don Jones

TechNet Magazine August 2008

...

Read more!

Despite its object oriented nature, Windows PowerShell is also able to parse complicated strings. Don Jones demonstrates how you can do this in Windows PowerShell using Select-String.

Don Jones

TechNet Magazine September 2008

...

Read more!

Don Jones shares his top six common suggestions to improve Windows PowerShell scripts.

Don Jones

TechNet Magazine July 2009

...

Read more!

Version 1 of Windows PowerShell offers less than impressive Active Directory management capabilities. Find out how you can use add-ins to get more powerful ways to work with Active Directory objects from within Windows PowerShell.

Don Jones

TechNet Magazine May 2008

...

Read more!

Popular Articles

Discover how to use the Excel.Application automation model for a more powerful way to process data from your servers and take advantage of the analysis and charting tools built into Excel.

The Microsoft Scripting Guys

TechNet Magazine January 2009

...

Read more!

Without too much effort, you can deploy a terminal server to host the applications you need in your environment. But there are some important decisions you’ll need to make to ensure your implementation meets user expectations. Greg Shields discusses the various options you have and explains how they will affect you.

Greg Shields

TechNet Magazine January 2009

...

Read more!

SQL Server 2008 includes a new “eventing” mechanism called SQL Server Extended Events that enables some sophisticated troubleshooting. Get an overview of Extended Events and find out how you can use this new functionality for monitoring and troubleshooting.

Paul S. Randal

TechNet Magazine January 2009

...

Read more!

Project Server 2007 delivers significant enhancements, not only to the features and functionality for users but also for administrators. Alan Maddison explores some of the most significant new features and walks you through the installation and configuration of Microsoft Office Project Server 2007.

Alan Maddison

TechNet Magazine January 2009

...

Read more!

Windows Vista SP1 and Windows Server 2008 introduce important changes to BitLocker, including support for data volumes and improved protection against cryptographic attacks. Byron Hynes explores the new features, demonstrates how to use BitLocker on a server, and discusses some of the recent media coverage affecting BitLocker.

Byron Hynes

TechNet Magazine June 2008

...

Read more!

Our Blog

NAP monitors the health of specified computers when they attempt to connect to a network and includes a number of mechanisms to enforce health requirements. In this article, Geek of All Trades Greg Shields gives readers an overview of these enforcement mechanisms and, as an example, takes a closer look at setting ...

Read more!

Use Windows PowerShell to Manage Virtual Machines Here are a few examples of how you can use Windows PowerShell scripts to manage virtual machines running on a Server Core installation. Note that these scripts are presented as samples and may need to be customized to work in your environment.

Create a New ...

Read more!

Disabling an Unused Part of Group Policy Objects One way to disable a policy is to disable an unused part of the GPO. By disabling part of a policy that isn’t used, the application of GPOs and security will be faster.

Administer Windows Server 2008 Server Core from the Command Prompt ...

Read more!

In the August 2008 issue of TechNet Magazine, Paul Randal wrote an article Top Tips for Effective Database Maintenance.  It was geared toward "involuntary  DBAs" (IT pros who inadvertently wind up responsible for a SQL Server instance).  The article had a great response from our readers so Paul has written another ...

Read more!

Microsoft Forefront is designed to deliver an integrated security solution that makes it much easier to deploy and manage security across an organization’s IT infrastructure. In this, our annual security issue, we feature two articles that describe how Forefront Security protects instant messaging and e-mail.

Protect ...

Read more!

Windows PowerShell Windows PowerShell Constructs
Don Jones


Last month, I showed you some ways in which Windows PowerShell could be put to immediate use solving administrative tasks—without actually writing any scripts. However, while Windows PowerShell is an excellent interactive shell, you can really take advantage of its capabilities and automate more complex tasks when you start to utilize its powerful-yet simple-scripting language.
First, though, you may be asking yourself: does Microsoft really need another scripting language? After all, Microsoft has brought us KiXtart, a logon script processor, as well as Visual Basic® Scripting Edition (VBScript). The answer, however, is yes. Microsoft really did need another scripting language. I'll explain why.
The Windows PowerShell™ language needed to be simple and intuitive, so administrators could pick it up without a lot of training. It also needed to be pretty flexible, so it could accommodate all the powerful functionality Windows PowerShell itself can provide to users.
Because Windows PowerShell is based on the Microsoft® .NET Framework, its scripting syntax needed to be .NET friendly. In assembling a scripting language for Windows PowerShell, the designers selected a syntax that's essentially a very simplified C# (pronounced C-Sharp, one of the languages that ships with the .NET Framework). Why not stick with a VBScript-like syntax? The Windows PowerShell scripting language isn't actually all that different from VBScript, but by sticking more closely to C# syntax, PowerShell provides a sort of initial stepping stone for learning .NET Framework programming. If you ever decide to move up to Visual Studio® and start writing C# applications, much of your Windows PowerShell scripting syntax will move up with you.
One of the most important things in the Windows PowerShell scripting language-or any scripting language, for that matter-is its constructs. These are special language elements that allow Windows PowerShell to perform logical comparisons and take different actions based on the comparisons' results or that allow it to repeat one or more instructions over and over.

Thinking Logically
Logical comparisons are at the heart of many scripting language constructs, and Windows PowerShell is no exception. A comparison essentially looks at two values or objects and evaluates whether the comparison is True or False. For example, you could ask yourself, "Is this user's password expiration date the same as today's date?" The result will either be True if the dates are the same or False if they are different. Note that I'm capitalizing True and False, because they're terms that have special meaning within Windows PowerShell.
Here's an example of a real logical comparison you could perform within Windows PowerShell:
PS C:\> $a = 1
PS C:\> $b = 2
PS C:\> $a -eq $b
False
I've created a variable named $a and set it to contain the value 1. In Windows PowerShell, variable names always begin with a dollar sign, so they're easy to spot. The = is technically referred to as the assignment operator, because it's used to assign a value. Next, I create a second variable, $b, and assign it the value 2. Then comes the actual logical comparison-I ask Windows PowerShell to compare the contents of $a and $b using the -eq (equality) operator. PowerShell performs the comparison, determines that the two values are not equal, and displays the result: False.
The Windows PowerShell operators are a bit different from other scripting languages you may have seen, and are even different from C#. Most languages will use the = operator to perform equality checks as well as for value assignment; Windows PowerShell avoids confusion by having a dedicated operator for each function. Figure 1 shows the Windows PowerShell comparison operators, along with equivalent operators in other languages (like VBScript) that you may be familiar with already.

Operator Name Description
-eq Equality Tests whether values are the same. Other languages may use = or == to test for equality.
-ne Not Equal Tests for inequality. Other languages may use <> or != to test for inequality.
-gt Greater Than Tests whether one value is larger than another. Other languages may use the > character.
-lt Less Than Tests whether one value is smaller than another. Other languages may use the < character.
-ge Greater Than or Equal To Tests whether a value is larger than or equal to another value. Similar to >= in VBScript and other languages.
-le Less Than or Equal To Tests whether a value is smaller than or equal to another value. Similar to <= in VBScript and other languages.
These comparison operators have another interesting feature. Take a look at this comparison:
PS C:\> $a = "TechNet"
PS C:\> $b = "technet"
PS C:\> $a -eq $b
True
By default, the comparison operators are case-insensitive, meaning the capitalized version of TechNet is seen as equivalent to "technet". That's convenient, because in most administrative tasks you don't care about the case of the letters. However, sometimes you may, and you can ask Windows PowerShell to perform a case-sensitive comparison by prepending the letter c to the comparison operator:
PS C:\> $a -ceq $b
False
Likewise, if you're ever concerned or confused about whether or not Windows PowerShell is going to perform a case-insensitive comparison, you can force it to do so by prepending the letter i:
PS C:\> $a -ieq $b
True
Just remember that logical comparisons always result in one of two values: True or False.

Making Decisions
Now that you know how to write logical comparisons, you can start using them in constructs. The first construct I'll show you allows Windows PowerShell to make decisions based on a comparison. It's called an If construct, and there are a few variations of it. Here's the simplest:
PS C:\> if ($a -eq $b) {
>> Write-Host "They are equal"
>> }
>>
They are equal
There are some interesting things to note here. First, the variables $a and $b still contain the values "TechNet" and "technet", respectively. I started the construct by using the If keyword. Following it, in parentheses, I entered the logical comparison I wanted to perform. Following that is a curly brace, which signals the start of what I'll call the conditional code-the code that Windows PowerShell will execute if the comparison returns a result of True. You know from the earlier example that this comparison does return True, so I'd expect the conditional code to execute. I type my conditional code, Write-Host "They are equal", and press Enter. Finally, I end the conditional code section by typing a closing curly brace, and tapping Enter twice. (The second Enter on a blank line lets the parser know that I'm done writing and ready for it to execute the code.)
Notice that this construct isn't running from a script file. I simply typed it into the Windows PowerShell com-mand line. This is what makes Windows PowerShell unique in the world of Windows scripting: scripts can be created interactively, as well as put into a file for permanent storage.
As soon as I typed the opening curly brace and pressed Enter, Windows PowerShell displayed a >> prompt. That's its way of saying, "I recognize that you're inside a construct, and I'm ready for you to start typing whatever goes inside the construct." After I typed the closing curly brace and tapped Enter twice, Windows PowerShell immediately executed the construct, determined that its logical comparison was True, and executed the conditional code. You can see this because "They are equal" was displayed before PowerShell returned to its normal prompt. Using Windows PowerShell to script interactively allows you to quickly test bits of code before assembling them into a more permanent script, which makes both learning and debugging easier.
I should point out that Windows PowerShell isn't especially picky about things like pressing Enter. For example, this is functionally the same as the previous example:
PS C:\> if ($a -eq $b) { Write-Host "They are equal" }
They are equal
Because I typed this all on one line, Windows PowerShell didn't need to display the special >> prompt; it simply executed the construct when I pressed Enter at the end of the line. How did Windows PowerShell know it was OK to execute the construct? Because it was complete at that point-the closing curly brace had been typed.
I alluded to other variations of the If construct. Here's a full example, presented as it might appear in a PS1 script file, rather than in the shell:
if ($a -eq $b) {
  Write-Host "They are equal"
} elseif ($a -lt $b) {
  Write Host "One is less than the other"
} else {
  Write Host "One is greater than the other"
}
The construct starts out the same, by using the If keyword. However, in the event that the comparison is False, I've provided another comparison by using the Elseif keyword. If that second comparison is also False, then my last keyword, Else, provides a final set of code that will execute.

Repeating Yourself
Windows PowerShell contains a couple of constructs for executing code over and over, until some comparison is either True or False. Programmers call these loop constructs. Even better, one of the most useful loop constructs is capable of enumerating the objects in a collection and executing one or more lines of code for each object. Appropriately enough, the construct is called a foreach construct, and it looks like this:
PS C:\> $names = get-content "c:\computers.txt"
PS C:\> foreach ($name in $names) {
>> Write-Host $name
>> }
>>
don-pc
testbed
I started by asking the Windows PowerShell Get-Content cmdlet to retrieve the contents of the c:\computers.txt file, a file I created myself that contains one computer name per line. Windows PowerShell treats each line as an object, so the file is essentially a collection that contains those objects. The collection winds up in the variable $names. Using the Foreach keyword, I tell Windows PowerShell to enumerate the $names collection, using the variable $name to represent the current object each time the loop executes. The loop code goes inside curly braces. So, for each name in the file, I'll output the name to the command line. And, as you can see from the output following the construct, that's exactly what Windows PowerShell does. You can see how this would provide an obvious benefit in administrative scripting: you could easily construct a list of server names, for example, and have Windows PowerShell retrieve information from each one in turn.

Real-World Constructs
So let's take logical comparisons, the If construct and the foreach construct, and do something useful. I want to quickly check the status of the Messenger service on a set of servers. I expect that the service will be stopped on most of the servers, so I don't want Windows PowerShell to list all the servers where the service is in the state I expect; I only want it to list the servers where the Messenger service is actually started because those are servers I need to do something about.
I know that the Windows PowerShell Get-Service cmdlet can help me retrieve the information I need for the local computer. Unfortunately, however, it can't reach out to a remote computer, which is really my goal. Happily, I can also access the same information via Windows Management Instrumentation (WMI), using the Get-WMIObject cmdlet, which lets me work with a remote computer. So here's the script:
$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started -eq $True ) {
    write-host "$name has Messenger running"
  }
}

Notice the ' character on the third line? It tells Windows PowerShell that the next line is a continuation. It's useful in cases like this where the entire line wouldn't fit in the magazine without wrapping. Also notice that my If construct compares $svc.started to $True. The variable $True is a special variable in Windows PowerShell that represents the Boolean True value. (A companion variable, $False, represents Boolean False.) Actually, I could have done a little shortcut there:
$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started) {
    write-host "$name has Messenger running"
  }
}
Remember that the If construct's condition simply needs to be True or False. Normally, you get True or False by comparing two values, as I did in the first version of this script. However, because the Started property is either True or False, there's no need to actually compare it to True or False.

One Useful Tool
So there you have it-a simple, useful administrative tool that utilizes constructs to do its job. Whether you type it into Windows PowerShell interactively, or save it in a PS1 file for easy reusability, it's a handy tool to check the status of a service on various computers and a great demonstration of how constructs can help automate administrative tasks.

Don Jones is the Director of Projects and Services for SAPIEN Technologies, and coauthor of Windows PowerShell: TFM (SAPIEN Press, 2006). Contact Don through his Web site at ScriptingAnswers.com.
© 2008 Microsoft Corporation and CMP Media, LLC. All rights reserved; reproduction in part or in whole without permission is prohibited.
Page view tracker