Click to Rate and Give Feedback
Related Articles
This is teh descriptionBla ...

Read more!

A tip on how to write amazing fast queries. ...

Read more!

This Tip will explain how to send email from Exchange ...

Read more!

Make a new tip by beating yourself in the head with a keyboard ...

Read more!

Also by this Author

For your users with attention span issues—and even those without—providing status feedback in your scripts is a good idea. Here's all you need to know to provide status in Windows PowerShell.

Don Jones

TechNet Magazine March 2008

...

Read more!

When designing Windows PowerShell, Microsoft gave security a leading role. And it shows. Take a look at some of the key security features and settings, such as credential handling and execution policies, that ensure Windows PowerShell won’t fall game to the same problems that VBScript enabled.

Don Jones

TechNet Magazine September 2007

...

Read more!

An overview of signing your scripts for improved security.

Don Jones

TechNet Magazine April 2008

...

Read more!

The pipeline isn't just for cmdlets. Take a look at how you can use the Windows PowerShell pipeline to add handy filtering capabilities to your scripts.

Don Jones

TechNet Magazine August 2007

...

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!

Popular Articles

While User Account Control offers an important improvement in security, the ability to elevate permissions is essential for accomplishing certain administrative tasks and functions. Here are some Elevation PowerToys that make elevation more flexible and powerful.

Michael Murgolo

TechNet Magazine June 2007

...

Read more!

Backup is something many people ignore until it’s too late. But there’s no excuse for this, especially now that the new Windows Vista Backup and Restore Center offers a variety of features that make it easy to protect your data against most forms of data loss. Find out how you can plan a complete recovery strategy with Windows Vista.

Christine Fok

TechNet Magazine September 2007

...

Read more!

See how this free utility can help you determine whether problems you are experiencing while running Windows are caused by faulty memory.

Lance Whitney

TechNet Magazine September 2008

...

Read more!

Windows Server 2008 and the new Windows Server Backup utility bring many changes and welcome enhancements to backing up. Here is an in-depth guide to backing up and restoring Active Directory in the new server OS.

Gil Kirkpatrick

TechNet Magazine May 2008

...

Read more!

Your users are complaining that a server is running poorly—do you know where to look to diagnose the problem? PerfMon can be an indispensible tool for this as it has numerous diagnostic capabilities. Get an overview of the key indicators you should use to diagnose a variety of common bottlenecks that can slow down your servers.

Steven Choy

TechNet Magazine August 2008

...

Read more!

Our Blog

Want to be proactive about preventing data loss? Enterprise rights management is the way to go. Discover how   the Microsoft Enterprise Rights Management solution can protect your organization's information from unauthorized access and use.

Read more!

Last year around this time, TechNet Magazine featured an article about the Microsoft Security Intelligence Report - a comprehensive study by the Microsft Malware Protection Center of the computer security landscape. Well, the latest SIR (volume 5) has just been released, and it's packed with a detailed analysis of current threats, as well as updates on available countermeasures. Head ...

Read more!

Proxy authentication lets users perform a simple bind to an Active Directory Lightweight Directory Services instance but still have an association to an Active Directory account. This can be very useful: it gives developers full access to a user object without giving them access to the Active Directory account, and it allows products that require the X.500 format to be used with Active Directory. ...

Read more!

In the November 2008 installment of our Windows PowerShell column (which is available online), Don Jones demonstrates how to create a tool that will inventory the operating system build number (this is one of the best ways to determine the OS version) and service pack version number from a list of computers.  ...

Read more!

"For developers, one difficult problem in SQL Server is tracking what data has changed in a database. An even greater challenge is architecting a simple solution that doesn’t heavily impact workload performance and isn't difficult to create, implement, and manage. So why go to all the trouble to track changes? Is tracking changes really worth all this effort? Two commonly cited examples are to support updates to a data warehouse and to support the synchronization of heterogeneous, occasionally connected systems." ...

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