Book Image

PowerShell: Automating Administrative Tasks

By : Michael Shepard, Chendrayan Venkatesan, Sherif Talaat, Brenton J.W. Blawat
Book Image

PowerShell: Automating Administrative Tasks

By: Michael Shepard, Chendrayan Venkatesan, Sherif Talaat, Brenton J.W. Blawat

Overview of this book

Are you tired of managing Windows administrative tasks manually and are looking to automate the entire process? If yes, then this is the right course for you. This learning path starts your PowerShell journey and will help you automate the administration of the Windows operating system and applications that run on Windows. It will get you up and running with PowerShell, taking you from the basics of installation to writing scripts and performing web server automation. You will explore the PowerShell environment and discover how to use cmdlets, functions, and scripts to automate Windows systems. The next installment of the course focuses on gaining concrete knowledge of Windows PowerShell scripting to perform professional-level scripting. The techniques here are packed with PowerShell scripts and sample C# code to automate tasks. You will use .NET classes in PowerShell and C# to manage Exchange Online. In the final section, you will delve into real-world examples to learn how to simplify the management of your Windows environment. You will get to grips with PowerShell’s advanced functions and how to most effectively administer your system. This Learning Path combines some of the best that Packt has to offer in one complete, curated package. It includes content from the following Packt products: [*] Getting Started with PowerShell by Michael Shepard [*] Windows PowerShell for .Net Developers Second Edition by Chendrayan Venkatesan and Sherif Talaat [*] Mastering Windows PowerShell Scripting by Brenton J.W. Blawat
Table of Contents (6 chapters)

Chapter 6. Scripts

Now that we have learned some useful commands, it would be nice to be able to record a sequence of commands, so that we can execute them all at once. In this chapter, we will learn how to accomplish this with scripts. We will also cover the following topics:

  • Execution policies
  • Adding parameters to scripts
  • Control structures
  • Profiles

Packaging commands

Saving commands in a file for reuse is a pretty simple idea. In PowerShell, the simplest kind of these files is called a script and it uses the .ps1 extension, no matter what version of PowerShell you're using. For example, if you wanted to create a new folder, under c:\temp, with the current date as the name and then change to that folder, you could put these commands in a file:

Packaging commands

Note that I'm using the top portion of the ISE to edit the file contents and I have saved the file as dateFolder.ps1 in the c:\temp folder. To run the script, you can simply type the name of the file at prompt as follows (in the bottom portion of the ISE):

Packaging commands

If you have the file loaded in the ISE, you can also use the Run button on the toolbar to run the current file.

It's possible that when you try to run this script, you will receive an error complaining about the execution policy, instead of seeing the current path being set to a new folder. To understand why this would have happened, we need to discuss the concept of execution policies.

Execution policy

Execution policy is a safety feature in PowerShell that enables the system to control which scripts are able to be run. I say safety instead of security because execution policy is trivial to circumvent. Execution policy are more like the safety of a gun, which prevents accidental discharge of the weapon. An execution policy is an attempt to prevent users from accidentally executing scripts.

Possible execution policy values include the following:

  • Restricted
  • AllSigned
  • RemoteSigned
  • Unrestricted

The Restricted setting means that the scripts cannot be run at all. AllSigned means that all scripts must be digitally signed to run. Unrestricted says that any script will run. RemoteSigned is a middle-ground setting that says that any local scripts will run, but scripts from remote sources (like the Internet or untrusted UNC paths) need to be digitally signed.

Prior to Windows Server 2012R2, the default execution policy for all systems was Restricted, meaning that by default scripts were not allowed to run at all. With Server 2012R2, the default was changed to RemoteSigned.

Attempting to run a script when the execution policy does not permit it, results in an error such as the following:

Execution policy

To see what your current execution policy is set to, use the Get-ExecutionPolicy cmdlet. To set the execution policy, you would use the Set-ExecutionPolicy cmdlet.

Tip

Important!

Since the execution policy is a system setting, changing it requires you to run an elevated session. Attempting to change the execution policy from a user session, will result in an "Access Denied" error writing to the registry.

The following figure shows the results of running the script after the execution policy has been set to an appropriate level:

Execution policy

In my experience, the RemoteSigned setting is most practical. However, in a secure environment such as a production data center, I can easily see that using an AllSigned policy could make sense.

Types of scripts

The PowerShell community often distinguishes between two different kinds of scripts. Some scripts, called controller scripts, call other cmdlets, scripts, and functions to complete a process. Controller scripts sometimes do more than one thing, but they are not meant for reuse, except perhaps as a step in a larger controller script. You might expect to find a controller script scheduled to run in the task scheduler. Tool scripts, on the other hand, are more focused, perform a single action, and are intended specifically to be reused. A tool script would never run on its own, let alone be scheduled. There aren't any technical differences between the two kinds of scripts, but there are things that would be considered best practices for one type that wouldn't be appropriate for the other. I find the distinction between the tools and controllers useful. When you write a script, think about whether it is a standalone process (controller), or it is something that you will use as a component in solving problems (tool).

Scopes and scripts

When you run a script, the PowerShell engine creates what is called a scope for the execution. If your script creates or modifies variables or functions (which we will discuss in later chapters), these changes will be created in the script's scope and will be removed at the end of the execution of the script. In the next chapter on PowerShell functions, we will see an important consequence of this, but for now we should just know that the things that are done in the script don't leave the script. As an example, here is a script that sets a variable to my name and outputs the variable to verify that it was correctly set. After executing the script, checking the variable shows that it is no longer set:

Scopes and scripts

If we need the things in the script to remain after its execution, PowerShell provides the ability to dot-source the file rather than just executing it. Dot-sourcing means to execute something, but to do it in the current scope and not create a child scope for it. The effect of dot-sourcing a script is the same as executing the commands in the script at the command-line—that is, all the effects of the script remain. To dot-source something, you use a period (a dot) and then a space, and then the name of the script.

If we dot-source the script from the previous example (instead of simply executing it), we can see that the $name variable retains the value that was set in the script:

Scopes and scripts

Parameters add flexibility

Executing a series of commands can be useful, but often you will want to execute the scripts and also provide some input—specific details about the execution of the script. One way to do this is to use parameters. Parameters are a way for you to provide the values that you want to be used in a script at execution time. For example, you might find that when you create a new directory, you immediately want to change to that directory. We started the chapter with a similar script that created a folder named with the current date, but because the script determined the folder name, we didn't need to provide any input. For this script, we don't know when we write the script what the name of the folder should be, but we will when we run it.

Parameters for scripts are specified in a Param() statement at the beginning of the script. The names of the parameters are variables and start with a dollar sign ($). You aren't limited to a single parameter, either. You can include multiple parameters, separating them with commas. We will spend a lot more time talking about parameters when we talk about functions, but the following screenshot should illustrate how to use parameters in scripts:

Parameters add flexibility

Adding some logic

PowerShell would not be very useful if scripts were limited to running one command after another without any logic. As expected from a modern language, PowerShell includes a full complement of control structures to allow you to vary the execution in just about any way you'd like. We will briefly introduce the most common control structures.

Conditional logic (IF)

The most simple logic statement is the If statement. The If statement allows you to have some code executed, if and only if a particular condition is met. In its simplest form, the If statement includes a condition in parentheses and a scriptblock to be executed when the condition is true:

Conditional logic (IF)

If there is another condition that should be executed if the first condition is false, you can include an Else clause:

Conditional logic (IF)

If you have multiple conditions to test, there is an ElseIf clause as well. Here's an example of its use:

Conditional logic (IF)

Looping logic

The most common way to loop in PowerShell is the ForEach statement. ForEach causes a scriptblock to be executed for each item in a collection. The ForEach statement lets you name the placeholder that is used to refer to the individual items in the collection. The syntax for the ForEach statement looks as follows:

ForEach ($placeholder in $collection){
  #Code goes here
}

As an example, we can display the extensions of all of the files in a folder using ForEach:

Looping logic

If you remember from Chapter 4, Life on the Assembly Line there is also a ForEach-Object cmdlet that works in a pipeline and executes a scriptblock for each item in the pipeline. To make things even more confusing, ForEach-Object has an alias called ForEach. It's easy to get confused between the ForEach statement and the ForEach-Object cmdlet, but remember that the ForEach statement does not work in a pipeline and lets you name the placeholder, so if it's in a pipeline, it has to be the ForEach-Object cmdlet.

More logic

There are other statements that can be used to structure scripts, but If and ForEach are by far the most common. If you need to use others, they are well documented in PowerShell's awesome help content.

For quick reference, some of the other statements include the following:

Statement

Purpose

While

Executes a scriptblock as long as a condition is true

Do..Until

Executes a scriptblock until a condition is true

For

Executes a scriptblock for each number in a range (like 1 to 10)

Conditional logic (IF)

The most simple logic statement is the If statement. The If statement allows you to have some code executed, if and only if a particular condition is met. In its simplest form, the If statement includes a condition in parentheses and a scriptblock to be executed when the condition is true:

Conditional logic (IF)

If there is another condition that should be executed if the first condition is false, you can include an Else clause:

Conditional logic (IF)

If you have multiple conditions to test, there is an ElseIf clause as well. Here's an example of its use:

Conditional logic (IF)

Looping logic

The most common way to loop in PowerShell is the ForEach statement. ForEach causes a scriptblock to be executed for each item in a collection. The ForEach statement lets you name the placeholder that is used to refer to the individual items in the collection. The syntax for the ForEach statement looks as follows:

ForEach ($placeholder in $collection){
  #Code goes here
}

As an example, we can display the extensions of all of the files in a folder using ForEach:

Looping logic

If you remember from Chapter 4, Life on the Assembly Line there is also a ForEach-Object cmdlet that works in a pipeline and executes a scriptblock for each item in the pipeline. To make things even more confusing, ForEach-Object has an alias called ForEach. It's easy to get confused between the ForEach statement and the ForEach-Object cmdlet, but remember that the ForEach statement does not work in a pipeline and lets you name the placeholder, so if it's in a pipeline, it has to be the ForEach-Object cmdlet.

More logic

There are other statements that can be used to structure scripts, but If and ForEach are by far the most common. If you need to use others, they are well documented in PowerShell's awesome help content.

For quick reference, some of the other statements include the following:

Statement

Purpose

While

Executes a scriptblock as long as a condition is true

Do..Until

Executes a scriptblock until a condition is true

For

Executes a scriptblock for each number in a range (like 1 to 10)

Looping logic

The most common way to loop in PowerShell is the ForEach statement. ForEach causes a scriptblock to be executed for each item in a collection. The ForEach statement lets you name the placeholder that is used to refer to the individual items in the collection. The syntax for the ForEach statement looks as follows:

ForEach ($placeholder in $collection){
  #Code goes here
}

As an example, we can display the extensions of all of the files in a folder using ForEach:

Looping logic

If you remember from Chapter 4, Life on the Assembly Line there is also a ForEach-Object cmdlet that works in a pipeline and executes a scriptblock for each item in the pipeline. To make things even more confusing, ForEach-Object has an alias called ForEach. It's easy to get confused between the ForEach statement and the ForEach-Object cmdlet, but remember that the ForEach statement does not work in a pipeline and lets you name the placeholder, so if it's in a pipeline, it has to be the ForEach-Object cmdlet.

More logic

There are other statements that can be used to structure scripts, but If and ForEach are by far the most common. If you need to use others, they are well documented in PowerShell's awesome help content.

For quick reference, some of the other statements include the following:

Statement

Purpose

While

Executes a scriptblock as long as a condition is true

Do..Until

Executes a scriptblock until a condition is true

For

Executes a scriptblock for each number in a range (like 1 to 10)

More logic

There are other statements that can be used to structure scripts, but If and ForEach are by far the most common. If you need to use others, they are well documented in PowerShell's awesome help content.

For quick reference, some of the other statements include the following:

Statement

Purpose

While

Executes a scriptblock as long as a condition is true

Do..Until

Executes a scriptblock until a condition is true

For

Executes a scriptblock for each number in a range (like 1 to 10)

Profiles

Profiles are special scripts that PowerShell hosts run automatically when they start a new session. Each host looks in four different locations for profile scripts, running any of them that it finds. To find where these locations are, for the host you're in, look at the $profile automatic variable:

Profiles

The first thing you'll notice is that there's only one path listed. To see all of them, you have to look at the extra properties that have been spliced onto $profile:

Profiles

The names of these properties should give you a good idea when each of them is used. The AllHosts profiles are used by all the hosts. The AllUsers profiles are used by all the users. The CurrentHost profiles are used by the host you're in (console or ISE). The CurrentUser profiles are specific to the user running this PowerShell session. It might be helpful to see the output of the same command from the PowerShell console instead of the ISE. The AllHosts profiles are the same, but the CurrentHost profiles are different, specific to that host.

Profiles

You can put any code you want in your profile. At this point in Module 1, we don't have a lot of things that would be useful, but we could at least change the directory to a more useful location than $PSHome. Since profiles are scripts, they are subject to the execution policy limitations. This means if your execution policy is still set to Restricted, the host won't be able to run your profile script, even if it is in the right place. Similarly, if your execution policy is AllSigned, you would need to digitally sign your profile scripts.

Summary

Scripts offer a useful way to combine commands and reuse them later. In this chapter, we saw how to create and execute scripts. We learned about using parameters to make scripts more flexible and how to incorporate logic into a script using a few control structures.

In the next chapter, we will look at another way to package code for reuse: namely, functions.

For further reading

  • Get-Help about_scripts
  • Get-Help about_execution_policies
  • Get-Help Set-ExecutionPolicy
  • Get-Help about_scopes
  • Get-Help about_parameters
  • Get-Help about_profiles
  • Get-Help about_if
  • Get-Help about_foreach
  • Get-Help about_switch
  • Get-Help about_do
  • Get-Help about_while
  • Get-Help about_switch
  • Get-Help about_for
  • Get-Help about_break
  • Get-Help about_continue