Downloads
100141.zip

Executive Summary: Lesson 2 in Robert Sheldon's PowerShell 201 series covers the if, for, and while statements. This lesson explains the various components that make up these statementsand provides examples of how to use each type of statement for tasks such as retrieving a list of text files in a folder and retrieving a list of processes and the number of handles used by those processes.

Windows PowerShell provides several ways to control the flow of code, including the if, for, and while statements. You can use these three statements to define conditions and the actions to occur when those conditions are met. You can even specify the actions to occur when a condition isn’t met. Let’s look at the various components that make up the if, for, and while statements and how to use each type of statement for tasks such as retrieving a list of text files in a folder and retrieving a list of processes and the number of handles they’re using.

The if Statement
An if statement contains a conditional code block, which is enclosed in parentheses, and a script block, which is enclosed in braces. The conditional code block specifies a condition, whereas the script block specifies one or more actions. When the condition is met—that is, when the conditional code block evaluates to true—PowerShell runs the script block. When the conditional code block evaluates to false, PowerShell skips the script block.

For example, the following code initializes the $files variable, then defines a basic if statement:

$files = dir c:\archivedfiles\*.txt
if ($files -ne $null)
\{
  "There are files in this folder."
  write-host
\}

The first line assigns a collection of text files to $files. The if statement uses the $files variable in its conditional code block ($files -ne $null) to specify that the variable must not be null. In other words, the variable must contain text files. When there are text files, the conditional code block evaluates to true and the script block runs and displays the message There are files in this folder. When the conditional code block evaluates to false, the if statement ends. As a result, no message is displayed when the folder doesn’t contain text files.

At times, you might want to take a specific action when a conditional code block evaluates to false. You can do so by adding an else clause. This clause begins with the keyword else, followed by its own script block. The else script block runs when none of the if statement’s conditional code blocks evaluate to true. Take, for example, the following if statement:

$files = dir c:\archivedfiles\*.doc
if ($files -ne $null)
\{
  "There are Word " +
  "files in this folder."
  write-host
\}
else
\{
  "No Word files in this folder."
  write-host
\}

When the conditional code block ($files -ne $null) evaluates to false, the else script block runs and displays the message No Word files in this folder.

In this example, the if statement takes into account two scenarios: the folder contains Microsoft Word files or doesn’t contain them. However, there might be times when you want the statement to handle more than two scenarios. In these situations, you can add a few elseif clauses. (If you need to use many elseif clauses, you should consider using a switch statement, which I’ll discuss in the next lesson.) For each elseif clause, you define a conditional code block and a script block. When the conditional code block evaluates to true, the script block runs.

For example, the code in Listing 1 uses elseif clauses to determine how many files are in a folder. In this code, one if statement is embedded in another if statement. The code begins by assigning a collection of text files to $files. The outer if statement then checks to see whether $files is null. I perform this check rather than using the Count property to determine the number of files because I had to provide for the possibility that there might be only one file in the folder. The Count property is available only when there’s two or more files in a folder. When there’s more than one file, PowerShell treats $files as an array, which supports the Count property. When there’s only one file, PowerShell treats $files as a scalar (i.e., single) value, which means the Count property isn’t available.

When the outer if statement finds that $files is null, the else clause in callout B runs. This clause’s script block displays the message No files in folder. When $files isn’t null, the inner if statement in callout A runs. The inner if statement’s conditional code block defines three conditions: an if condition and two elseif conditions.

The if condition ($files.count -gt 10) specifies that the number of text files must be greater than 10. When this conditional code block evaluates to true, the script block displays the message More than 10 files in folder.

The first elseif condition ($files.count -gt 7 -and $files.count -le 10) specifies that the number of text files must be greater than 7 but less than or equal to 10. When this conditional code block evaluates to true, the script block displays the message 8-10 files in folder.

The second elseif condition ($files.count -gt 4 -and $files.count -le 7) specifies that the number of text files must be greater than 4 but less than or equal to 7. When that conditional code block evaluates to true, the script block displays the message 5-7 files in folder.

If none of the three conditional code blocks evaluate to true, the else clause’s script block runs. It displays the message Fewer than 5 files in folder.

Continue to page 2

As Listing 1, demonstrates, you can embed if statements in the script block of another if statement, but you aren’t limited to embedding only these types of statements. You can, for example, embed a foreach statement in an if statement’s script block, as shown in Listing 2. The foreach statement runs only when the if statement’s conditional code block evaluates to true. In other words, when the folder contains text files, the foreach statement will loop through those text files. Each time a loop runs, foreach returns the text file’s size, as Figure 1, shows.

The for Statement
In Lesson 1, I showed you how to implement foreach loops to iterate through a collection. You can also use for statements to loop through collections. A for statement implements a counting loop that iterates through a collection as long as the condition is true. Like if statements, for statements include a conditional code block and a script block. However, the for statement’s conditional code block is more complex.

Let’s take a look at a simple example. The following for statement displays the values assigned to the $a variable:

for ($a = 1; $a -le 5; $a++) \{$a\}

The statement begins with the keyword for, followed by the conditional code block ($a = 1; $a -le 5; $a++). The for statement’s conditional code block is made up of three parts, which are separated by semicolons. The first part ($a = 1) initializes the $a variable with the value 1. The $a variable provides a base value, or starting value, for the other code block elements.

The second part ($a -le 5) is the condition itself. In this case, the value in $a must be less than 5 to evaluate to true. The third part ($a++) increments $a by 1 at the end of each loop. As a result, the statement will continue to step through the collection as long as the value in $a is less than or equal to 5. When $a equals 6, the for statement ends. Figure 2 shows sample output from this statement.

In some cases, you won’t know the number of elements in a collection. The code in Listing 3 demonstrates how you can use a for statement to iterate through such collections. This code begins by storing a collection of text files in the $files variable. The if statement uses the $files variable and its Count property ($files.count) to check the file count. As I mentioned previously, if there’s only one file in the collection, PowerShell returns an object (i.e., a System .IO.FileSystemInfo object) that has a scalar value. If there are no files, PowerShell doesn’t return an object. In either case, the Count property doesn’t exist. As a result, you receive a null value if you try to call the Count property, which is why you can use it as a condition in the if statement.

When $files.count returns a null value, the elseif clause in callout B checks for the condition of there being only one file. If this condition isn’t met, there are no files and the else clause in callout C runs.

When $files.count doesn’t return a null value (i.e., PowerShell returns a System .Array object so the Count property exists), the code in callout A runs because there are at least two files. In callout A, the embedded for statement’s conditional code block uses the Count property to determine the exact number of files (i.e., elements) in the collection. As long as $i is less than the number of elements, the condition evaluates to true.

Note that I initialize $i to 0. I use 0 because collections (such as $files) use base 0 indexing. In the script block, I use $i to specify which element to retrieve from the collection. For instance, during the first loop, $i is set to 0. This means that $files\[$i\] is the same as $files\[0\]. On the second loop, $i equals 1, so the value becomes $files\[1\], and so on. Figure 3 shows sample results from the code in Listing 3.

One other item worth pointing out is that you can declare and initialize the base variable before the for statement. For example, in Listing 4, the $i variable is declared and initialized in the line highlighted by callout A. As you can see, the code is easier to read with this setup.

The while Statement
Like the for statement, the while statement is a type of loop that iterates through a collection. The while statement, which consists of a conditional code block and a script block, continues as long as the conditional code block evaluates to true. The following code provides a simple example of how this works:
$count = 0
while ($count -lt 5)
\{
  $count++
  "The count is
  $count."
\}

The first line of code initializes the $count variable to 0. This variable is used as a base or starting value for the looping. The conditional code block ($count -lt 5) specifies that $count must be less than 5.

When the conditional code block evaluates to true, the script block runs. The first statement in the script block increments $count by 1. The second statement outputs a string that displays the running value in $count, as shown in the results:

The count is 1.
The count is 2.
The count is 3.
The count is 4.
The count is 5.

Note that when $count is 4 in the conditional code block, the script block increments $count by 1 and displays a value of 5 in the output. It’s not until the next time through the loop that the conditional code block evaluates to false, ending the while loop.

Sometimes you might not know the number of elements in a collection that’s being iterated through with a while loop. In this situation, you can use the Count property to retrieve that value:

$proc = Get-Process
$count = 0
while ($count -lt
$proc.count)
\{
  "The " +
    $proc\[$count\].name +
    " process uses " +
    $proc\[$count\].handles +
    " handles."
  $count ++
\}

This code first assigns the results of the Get-Process cmdlet to the $proc variable. This cmdlet returns a list of processes running on the local system. The conditional code block in the while loop specifies that the value in $count must be less than the total number of processes ($proc.count). Figure 4 shows sample results from running this code. As you can see, you can use the $proc variable to retrieve not only the number of processes but also each process’s name and number of handles.

Moving Forward
In this lesson, you learned about the if, for, and while statements. These statements, along with the foreach statement and ForEach-Object cmdlet discussed in Lesson 1, provide a wide range of tools for implementing flow-control statements. You should try out all these statements and try to combine them in different ways, such as adding if statements to foreach statements. The more comfortable you become with using these statements, the better you’ll understand them and be able to implement them in your code.