Introduction to scripting in PowerShell
Posted by Superadmin on January 29 2023 05:01:06

Introduction to scripting in PowerShell

 

 

This module introduces you to scripting with PowerShell. It introduces various concepts to help you create script files and make them as robust as possible.

Learning objectives

 

 

Prerequisites

Introduction

 

In this module, you'll learn the basics of PowerShell scripting. Scripting is about automation. It's about storing steps that you do often in a file. By running files that contain your scripts, you can save time and reuse existing solutions. You can then spend that time on something more valuable.

In this module, you'll learn some helpful constructs of the PowerShell language and how you can use them to create and run scripts.

Learning objectives

After completing this module, you'll be able to:

Introduction to scripting

 

PowerShell scripting is the process of writing a set of statements in the PowerShell language and storing those statements in a text file. Why would you do that? After you use PowerShell for a while, you find yourself repeating certain tasks, like producing log reports or managing users. When you've repeated something frequently, it's probably a good idea to automate it: to store it in such a way that makes it easy to reuse.

The steps to automate your task usually include calls to cmdlets, functions, variables, and more. To store these steps, you'll create a file that ends in .ps1 and save it. You'll then have a script you can run.

Before you start learning to script, let's get an overview of the features of the PowerShell scripting language:

Run a script

You need to be aware that some scripts aren't safe. If you find a script on the internet, you probably shouldn't run it on your computer unless you understand exactly what it does. Even with scripts you consider safe, there might be a risk. For example, imagine a script that cleans things up in a test environment. That script might be harmful in a production environment. You need to understand what a script does, whether it was written by you or by a colleague or if you got it from the internet.

PowerShell attempts to protect you from doing things unintentionally in two main ways:

These two mechanisms don't stop you from opening a file, copying its contents, placing the contents in a text file, and running the file. They also don't stop you from running the code via the console. These mechanisms help to stop you from doing something unintentional. They aren't a security system.

To create and run a script:

  1. Create some PowerShell statements like the following and save them in a file that ends with .ps1:

    PowerShell
    # PI.ps1
    $PI = 3.14
    Write-Host "The value of `$PI is $PI"
    
  2. Run the script by invoking it by its name and path:

      Note

    Before you run the script, ensure the current shell is PowerShell. Alternatively, on Linux or macOS, you can put a shebang at the top of the script file to define PowerShell as the script interpreter.

    Bash 
    ./PI.ps1
    

    We recommend you include the file extension in the invocation, but it's not required.

Execution policy

You can manage execution policy using these cmdlets:

Variables

Variables aren't just for scripts. You can also define them on the console. You can store values in variables so you can use them later. To define a variable, precede it with the $ character. Here's an example:

PowerShell
$PI = 3.14

Working with variables: Quotation marks and interpolation

When you output text via Write-Host or Write-Output, you can use single or double quotation marks. Your choice depends on whether you want to interpolate the values. There are three mechanisms you should know about:

Scope

Scope is how PowerShell defines where constructs like variables, aliases, and functions can be read and changed. When you're learning to write scripts, you need to know what you have access to, what you can change, and where you can change it. If you don't understand how scope works, your code might not work as you expect it to.

Types of scope

Let's talk about the various scopes:

Scope rules

Scope rules help you understand what values are visible at a given point. They also help you understand how to change a value.

Write-Host $test # Prints hi

Profiles

A profile is a script that runs when PowerShell starts. You can use a profile to customize your environment to, for example, change background colors and errors and do other types of customizations. PowerShell will apply these changes to each new session you start.

Profile types

PowerShell supports several profile files. You can apply them at various levels, as you see here:

DescriptionPath
All users, all hosts $PSHOME\Profile.ps1
All users, current host $PSHOME\Microsoft.PowerShell_profile.ps1
Current user, all hosts $Home[My ]Documents\PowerShell\Profile.ps1
Current user, current host $Home[My ]Documents\PowerShell\Microsoft.PowerShell_profile.ps1

 

There are two variables here: $PSHOME and $Home$PSHOME points to the installation directory for PowerShell. $Home is the current user's home directory.

 

Other programs also support profiles, like Visual Studio Code.

Create a profile

When you first install PowerShell, there are no profiles, but there is a $Profile variable. It's an object that points to the path where each profile to apply should be placed. To create a profile:

  1. Decide the level on which you want to create the profile. You can run $Profile | Select-Object * to see the profile types and the paths associated with them.

  2. Select a profile type and create a text file at its location by using a command like this one: New-Item -Path $Profile.CurrentUserCurrentHost.

  3. Add your customizations to the text file and save it. The next time you start a session, your changes will be applied.

Exercise - Scripting

 

Set up a profile

A profile is a script that runs when you start a new session. Having a customized environment can make you more productive.

  1. Enter pwsh in a terminal window to start a PowerShell session:

    Bash
    pwsh
    
  2. Run this command:

    PowerShell
    $Profile | Select-Object *
    

    The output will display something similar to this text:

    Output
    CurrentUserAllHosts                        CurrentUserCurrentHost
    -------------------                        ----------------------
    /home/<user>/.config/PowerShell/profile.ps1 /home/<user>/.config/PowerShell/Microsoft.…
    
  3. Create a profile for the current user and the current host by running the command New-Item:

    PowerShell
    New-Item `
      -ItemType "file" `
      -Value 'Write-Host "Hello <replace with your name>, welcome back" -foregroundcolor Green ' `
      -Path $Profile.CurrentUserCurrentHost -Force
    

    The -Force switch will overwrite existing content, so be careful if you run this locally and have an existing profile.

  4. Run pwsh to create a new shell. You should now see the following (in green):

    Output
    Hello <your name>, welcome back
    

Create and run a script

Now that you have a profile set up, it's time to create and run a script.

  1. Ensure you have an existing PowerShell session running. In the console window, enter this code:

    PowerShell
$PI = 3.14
  1. Create a file named PI.ps1 in the current directory and open it in your code editor:

    PowerShell
    New-Item -Path . -Name "PI.ps1" -ItemType "file"
    code PI.ps1
    
  2. Add the following content to the file and save it. You can use CTRL+S on Windows and Linux or CMD+S on Mac to save your file.

    PowerShell
    $PI = 3
    Write-Host "The value of `$PI is now $PI, inside the script"
    
  3. Run the script by specifying the path to it:

    Bash
    ./PI.ps1
    

    Your output displays the following text:

    Output
    The value of $PI is now 3, inside the script
    

    Your script does two things. First, it creates a script-local variable $PI that shadows the $PI variable defined in the local scope. Next, the second row in the script interpolates the $PI variable because you used double quotation marks. It escapes interpolation the first time because you used a back tick.

  4. Enter $PI in the console window:

    Output
    3.14
    

    The value is still 3.14. The script didn't change the value.

 

 

 

Parameters

 

 

After you've created a few scripts, you might notice your scripts aren't flexible. Going into your scripts to change them isn't efficient. There's a better way to handle changes: use parameters.

Using parameters makes your scripts flexible, because it allows users to select options or send input to the scripts. You won't need to change your scripts as frequently, because in some cases you'll just need to change a parameter value.

Cmdlets, functions, and scripts all accept parameters.

Declare and use a parameter

To declare a parameter, you need to use the keyword Param with an open and close parenthesis:

PowerShell
Param()

Inside the parentheses, you define your parameters, separating them with commas. A typical parameter declaration might look like this:

PowerShell
# CreateFile.ps1
Param (
  $Path
)
New-Item $Path # Creates a new file at $Path.
Write-Host "File $Path was created"

The script has a $Path parameter that's later used in the script to create a file. The script is now more flexible.

Use the parameter

To call a script with a parameter, you need to provide a name and a value. Assume the above script is called CreateFile.ps1. You could call it like this:

PowerShell
./CreateFile.ps1 -Path './newfile.txt' # File ./newfile.txt was created.
./CreateFile.ps1 -Path './anotherfile.txt' # File ./anotherfile.txt was created.

Because you used a parameter, you don't need to change the script file when you want to call the file something else.

  Note

This particular script might not benefit much from using a parameter, because it only calls New-Item. As soon as your script is a few lines long, using the parameter will pay off.

Improve your parameters

When you first create a script that uses parameters, you might remember exactly what the parameters are for and what values are reasonable for them. As time passes, you might forget those details. You might also want to give a script to a colleague. The solution in these cases is to be explicit, which makes your scripts easy to use. You want a script to fail early if it passes unreasonable parameter values. Here are some things to consider when you define parameters:

Select an approach

All parameters are optional by default. That default might work in some cases, but sometimes you need your user to provide parameter values, and the values need to be reasonable ones. If the user doesn't provide a value to a parameter, the script should quit or tell the user how to fix the problem. The worst scenario is for the script to continue and do things you don't want it to do.

There are a couple of approaches you can use to make your script safer. You can write custom code to inspect the parameter value. Or, you can use decorators that do roughly the same thing. Let's look at both approaches.

These three approaches aren't mutually exclusive. You can combine them to make your script safer.

 

 

 

 

 

Exercise - Parameters

Create a backup script

A common task is to create a backup. A backup is usually a compressed file that stores all the files belonging to, for example, an app. When you installed PowerShell, you got the cmdlet Compress-Archive, which can help you complete this task.

  1. In your Cloud Shell terminal, run these bash commands:

    Bash
    mkdir app
    cd app
    touch index.html app.js
    cd ..
    

    You should now have a directory named app. You're ready to work with PowerShell.

  2. In the same terminal, start a PowerShell shell (if it's not already started) by running pwsh:

    Bash
    pwsh
    
  3. Create a script file named Backup.ps1 in the current directory and open it in your code editor.

    Bash
    touch Backup.ps1
    code Backup.ps1
    
  4. Add this content to the file and save the file. You can use CTRL-S on Windows and Linux or CMD+S on Mac to save.

    PowerShell
    $date = Get-Date -format "yyyy-MM-dd"
    Compress-Archive -Path './app' -CompressionLevel 'Fastest' -DestinationPath "./backup-$date"
    Write-Host "Created backup at $('./backup-' + $date + '.zip')"
    

    The script invokes Compress-Archive and uses three parameters:

    • -Path is the directory of the files that you want to compress.
    • -CompressionLevel specifies how much to compress the files.
    • -DestinationPath is the path to the resulting compressed file.
  5. Run the script:

    PowerShell
    ./Backup.ps1 
    

    You should see this output:

    Output
    Created backup at ./backup-<current date as YYYY-MM-DD>.zip
    

Add parameters to your script

If you add parameters to your script, users can provide values when it runs. You'll add parameters to your backup script to enable configuration of the locations of the source files and the resulting zip file.

  1. Add the following code to the top of the Backup.ps1 file.

      Note

    Use the code Backup.ps1 command to open the file if the editor isn't open.

    PowerShell
    Param(
      [string]$Path = './app',
      [string]$DestinationPath = './'
    )
    

    You've added two parameters to your script: $Path and $DestinationPath. You've also provided default values so users don't need to provide the values. Users can override the default values if they need to. You need to adjust the script to use these parameters. You'll do so next.

  2. Change the code in the file to use the parameters, then save the file. Backup.ps1 should now look like this:

    PowerShell
    Param(
      [string]$Path = './app',
      [string]$DestinationPath = './'
    )
    $date = Get-Date -format "yyyy-MM-dd"
    Compress-Archive -Path $Path -CompressionLevel 'Fastest' -DestinationPath "$($DestinationPath + 'backup-' + $date)"
    Write-Host "Created backup at $($DestinationPath + 'backup-' + $date + '.zip')"
    
  3. Rename your app directory to webapp by running this command:

    Bash
    mv app webapp
    

    Renaming the app directory simulates the fact that not all directories you'll need to back up will be called app.

    You can no longer rely on the default value for $Path. You'll need to provide a value via the console when you run the script.

  4. Remove your backup file, replacing <current date as YYYY-MM-DD> with the current date:

    Bash
    rm backup-<current date as YYYY-MM-DD>.zip
    

    You're removing this file to make sure you get a message stating that your $Path value doesn't exist. Otherwise, you'd get a message about the zip file already existing, and the problem we're trying to fix would be hidden.

  5. Run your script without providing parameters. (The script will use default values for the parameters.)

    Bash
    ./Backup.ps1
    

    You'll see an error message similar to this one:

    Output
    Line |
       8 |  Compress-Archive -Path $Path -CompressionLevel 'Fastest' -Destination …
         |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         | The path './app' either does not exist or is not a valid file system path.
    Created backup at ./backup-<current date as YYYY-MM-DD>.zip
    

    The script notifies you that it can't find the directory ./app. Now it's time to provide a value to the $Path parameter and see the benefit of adding parameters to your script.

  6. Test your script by running it:

    PowerShell
    ./Backup.ps1 -Path './webapp'
    

    You'll see a message similar to the one you got earlier:

    Output
    Created backup at ./backup-<current date as YYYY-MM-DD>.zip
    

    You can now use parameters if the directory you want to back up isn't called ./app or if you want to put the compressed file somewhere other than the current directory.

Congratulations. You created a backup script that you can use whenever you want to create a backup for an app directory or any other important directory. You then identified parts of your script that might need to change often and replaced static values with parameter values. That way, you most likely won't need to change the script itself when your requirements change (for example, if the name of the app changes or you need to name the destination file something else).

 

 

 

Flow control

 

 

Flow control refers to how your code runs in your console or script. It describes the flow the code follows and how you control that flow. There are various constructs available to help you control the flow. The code can run all the statements, or only some of them. It can also repeat certain statements until it meets a certain condition.

Let's examine these flow-control constructs to see what they can do:

Manage input and execution flow by using IfElseIf, and Else

You can use an If construct to determine if an expression is True or False. Depending on that determination, you might run the statement defined by the If construct. The syntax for If looks like this:

PowerShell
If (<expression that evaluates to True or False>) 
{
  # Statement that runs only if the preceding expression is $True.
}

Operators

PowerShell has two built-in parameters to determine if an expression is True or False:

You can use operators to determine if an expression is True or False. There are a few operators. The basic idea is usually to determine if something on the left side of the operator matches something on the right side, given the operator's condition. An operator can express conditions like whether something is equal to something else, larger than something else, or matches a regular expression.

Here's an example of using an operator. The -le operator determines if the value on the left side of the operator is less than or equal to the value on the right side:

PowerShell
$Value = 3
If ($Value -le 0) 
{
  Write-Host "Is negative"
}

This code won't display anything because the expression evaluates to False. The value 3 is clearly positive.

Else

The If construct runs statements only if they evaluate to True. What if you want to handle cases where they evaluate to False? That's when you use the Else construct. If expresses "if this specific case is true, run this statement." Else doesn't take an expression. It captures all cases where the If clause evaluates to False. When If and Else are combined, the code runs the statements in one of the two constructs. Let's modify the previous code to include an Else construct:

PowerShell
$Value = 3
If ($Value -le 0) 
{
  Write-Host "Is negative"
} Else {
  Write-Host "Is Positive"
}

Because we put the Else next to the ending brace for the If, we created a joined construct that works as one. If you run this code in the console, you'll see that Is Positive prints. That's because If evaluates to False, but Else evaluates to True. So Else prints its statement.

 Note

You can use Else only if there's an If construct defined immediately above it.

ElseIf

If and Else work great to cover all the paths code can take. ElseIf is another construct that can be helpful. ElseIf is meant to be used with If. It says "the expression in this construct will be evaluated if the preceding If statement evaluates to False." Like IfElseIf can take an expression, so it helps to think of ElseIf as a secondary If.

Here's an example that uses ElseIf:

PowerShell
# _FullyTax.ps1_
# Possible values: 'Minor', 'Adult', 'Senior Citizen'
$Status = 'Minor'
If ($Status -eq 'Minor') 
{
  Write-Host $False
} ElseIf ($Status -eq 'Adult') {
  Write-Host $True
} Else {
  Write-Host $False
}

It's possible to write this code in a more compact way, but this way does show the use of ElseIf. It shows how If is evaluated first, then ElseIf, and then Else.

 Note

As with Else, you can't use ElseIf if you don't define an If above it.

 

 

 

 

Exercise - Flow control

 

If you haven't completed the previous exercises in this module, run the following bash commands in a terminal:

Bash
mkdir webapp
cd webapp
touch index.html app.js
cd ..

 

Add checks to your script parameters

You've been working with a backup script so far, and you've been adding parameters to it. You can make your script even safer to use by adding checks that ensure the script only continues if it's provided reasonable parameter inputs.

Let's look at the current script. If you completed the previous exercise, you should have a file called Backup.ps1. If not, create the file and open it in your code editor:

Bash
touch Backup.ps1
code Backup.ps1

Add this code to the file:

PowerShell
Param(
  [string]$Path = './app',
  [string]$DestinationPath = './'
)
$date = Get-Date -format "yyyy-MM-dd"
Compress-Archive -Path $Path -CompressionLevel 'Fastest' -DestinationPath "$($DestinationPath + 'backup-' + $date)"
Write-Host "Created backup at $($DestinationPath + 'backup-' + $date + '.zip')"

As you know, the script will stop responding if $Path points to a directory that doesn't exist.

  1. Use an existing PowerShell shell if you have one running. Otherwise, start one by typing pwsh in a terminal:

    Bash
    pwsh
    
  2. Add a check for the $Path parameter by adding this code right after the Param section, then save the file:

    PowerShell
    If (-Not (Test-Path $Path)) 
    {
      Throw "The source directory $Path does not exist, please specify an existing directory"
    }
    

    You've added a test that checks if $Path exists. If it doesn't, you stop the script. You also explain to users what went wrong so they can fix the problem.

  3. Ensure the script works as intended by running it:

    PowerShell
    ./Backup.ps1 -Path './app'
    

    You should see this output:

    Output
    Throw "The source directory $Path does not exist, please specify  …
      |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      | The source directory ./app does not exist, please specify an
      | existing directory
    
  4. Test that the script still works as intended. (Be sure to remove any backup files from the previous exercise before you continue.)

    PowerShell
    ./Backup.ps1 -Path './webapp'
    

    You should see a message that looks similar to this one:

    Output
    Created backup at ./backup-2021-01-19.zip 
    

    If you run the script again, it will stop responding. It will notify you that the zip file already exists. Let's fix that problem. We'll add code to ensure the backup is created only if no other backup zip file from the current day exists.

  5. Replace the code in the file with this code, then save the file:

    PowerShell
    Param(
      [string]$Path = './app',
      [string]$DestinationPath = './'
    )
    If (-Not (Test-Path $Path)) 
    {
      Throw "The source directory $Path does not exist, please specify an existing directory"
    }
    $date = Get-Date -format "yyyy-MM-dd"
    $DestinationFile = "$($DestinationPath + 'backup-' + $date + '.zip')"
    If (-Not (Test-Path $DestinationFile)) 
    {
      Compress-Archive -Path $Path -CompressionLevel 'Fastest' -DestinationPath "$($DestinationPath + 'backup-' + $date)"
      Write-Host "Created backup at $($DestinationPath + 'backup-' + $date + '.zip')"
    } Else {
      Write-Error "Today's backup already exists"
    }
    

    You did two things here. First, you created a new variable, $DestinationFile. This variable makes it easy to check if the path already exists. Secondly, you added logic that says "create the zip file only if the file doesn't already exist." This code implements that logic:

    PowerShell
    If (-Not (Test-Path $DestinationFile)) 
    {
      Compress-Archive -Path $Path -CompressionLevel 'Fastest' -DestinationPath "$($DestinationPath + 'backup-' + $date)"
      Write-Host "Created backup at $($DestinationPath + 'backup-' + $date + '.zip')"
    } Else {
      Write-Error "Today's backup already exists"
    }
    
  6. Run the code to make sure the script doesn't stop responding and that your logic is applied:

    Bash
    ./Backup.ps1 -Path './webapp' 
    

    You should see this output:

    Output
    Write-Error: Today's backup already exists
    

Congratulations. You've made your script a little safer. (Note that it's still possible to provide problematic input to $DestinationPath, for example.) The point of this exercise is to show how to add checks. Depending on the environment in which the script will run, you might want fewer or more checks. You might even want written tests; it all depends on the context.

 

 

 

 

Error handling

 

So far, you've seen how adding parameters and flow-control constructs can make your scripts flexible and safer to use. But sometimes, you'll get errors in your scripts. You need a way to handle those errors.

Here are some factors to consider:

Errors

A cmdlet or function, for example, might generate many types of errors. We recommend that you write code to manage each type of error that might occur, and that you manage them appropriately given the type. For example, say you're trying to write to a file. You might get various types of errors depending on what's wrong. If you're not allowed to write to the file, you might get one type of error. If the file doesn't exist, you might get another type of error, and so on.

There are two types of errors you can get when you run PowerShell:

Managing errors by using Try/Catch/Finally

You can think of a terminating error as an unexpected error. These errors are severe. When you deal with one, you should consider what type of error it is and what to do about it.

There are three related constructs that can help you manage this type of error:

Inspecting errors

We've talked about exception objects in the context of catching errors. You can use these objects to inspect what went wrong and take appropriate measures. An exception object contains:

So how do you inspect an exception object? There's a built-in variable, $_, that has an exception property. To get the error message, for example, you would use $_.exception.message. In code, it might look like this:

PowerShell
Try {
     # Do something with a file.
   } Catch [System.IO.IOException] {
     Write-Host "Something IO went wrong: $($_.exception.message)"
   }  Catch {
     Write-Host "Something else went wrong: $($_.exception.message)"
   }

Raising errors

In some situations, you might want to cause an error:

 

 

Exercise - Error handling

 

 

 

In this unit, you'll use Azure Cloud Shell on the right side of your screen as your Linux terminal. Azure Cloud Shell is a shell you can access through the Azure portal or at https://shell.azure.com. You don't have to install anything on your computer to use it.

In this exercise, you'll use a Try/Catch block to ensure the script stops responding early if a certain condition isn't met. You'll again work with your backup script.

Say you've noticed that you sometimes specify an erroneous path, which causes backup of files that shouldn't be backed up. You decide to add some error management.

  Note

Run the following commands only if you haven't completed any of the previous exercises in this module. We're assuming you've completed the previous exercises. If you haven't done so, you need a few files.

  1. If you haven't completed the previous exercises in this module, run the following bash commands in a terminal:

    Bash
    mkdir webapp
    cd webapp
    touch index.html app.js
    cd ..
    

    These commands will create a directory that contains files typically associated with web development.

  2. You also need a file named Backup.ps1. Run these commands:

    Bash
    touch Backup.ps1
    code Backup.ps1
    

    Now that you have an editor running, add the required code. Paste this code into the editor and save the file:

    PowerShell
    Param(
         [string]$Path = './app',
         [string]$DestinationPath = './'
       )
    
    If(-Not (Test-Path $Path)) 
    {
       Throw "The source directory $Path does not exist, please specify an existing directory"
    }
    
    $date = Get-Date -format "yyyy-MM-dd"
    
    $DestinationFile = "$($DestinationPath + 'backup-' + $date + '.zip')"
    If (-Not (Test-Path $DestinationFile)) 
    {
      Compress-Archive -Path $Path -CompressionLevel 'Fastest' -DestinationPath "$($DestinationPath + 'backup-' + $date)"
      Write-Host "Created backup at $($DestinationPath + 'backup-' + $date + '.zip')"
    } Else {
      Write-Error "Today's backup already exists"
    }
    

Implement a business requirement by using Try/Catch

Assume your company mostly builds web apps. These apps consist of HTML, CSS, and JavaScript files. You decide to optimize the script to recognize web apps.

  1. Use an existing PowerShell shell, if you have one running. Otherwise, start one by typing pwsh in a terminal:

    Bash
    pwsh
    
  2. Open Backup.ps1. In the Param section, add a comma after the last parameter, and then add the following parameter:

    PowerShell
    [switch]$PathIsWebApp
    

    You've added a switch parameter. If this parameter is present when the script is invoked, you perform the check on the content. After that, you can determine if a backup file should be created.

  3. Under the Param section, add this code, then save the file:

    PowerShell
    If ($PathIsWebApp -eq $True) {
       Try 
       {
         $ContainsApplicationFiles = "$((Get-ChildItem $Path).Extension | Sort-Object -Unique)" -match  '\.js|\.html|\.css'
    
         If ( -Not $ContainsApplicationFiles) {
           Throw "Not a web app"
         } Else {
           Write-Host "Source files look good, continuing"
         }
       } Catch {
        Throw "No backup created due to: $($_.Exception.Message)"
       }
    }
    

    The preceding code first checks if the parameter $PathIsWebApp is provided at runtime. If it is, the code continues to get a list of file extensions from the directory specified by $Path. In our case, if you run that part of the code on the webapp directory, the following code will print a list of items:

    PowerShell
    (Get-ChildItem $Path).Extension | Sort-Object -Unique
    

    Here's the output:

    Output
    .html
    .js
    

    In the full statement, we're using the -match operator. The -match operator expects a regular expression pattern. In this case, the expression states "do any of the file extensions match .html.js, or .css?" The result of the statement is saved to the variable $ContainsApplicationFiles.

    Then the If block checks whether the $ContainsApplicationFiles variable is True or False. At this point, the code can take two paths:

    • If the source directory is for a web app, the script writes out "Source files look good, continuing."
    • If the source directory isn't for a web app, the script throws an error that states "Not a web app." The error is caught in a Catch block. The script stops, and you rethrow the error with an improved error message.
  4. Test the script by providing the switch $PathIsWebApp:

     Note

    Before you run the script, make sure there are no .zip files present. They might have been created when you completed previous exercises in this module. Use Remove-Item *zip to remove them.

    PowerShell
    ./Backup.ps1 -PathIsWebApp -Path './webapp'
    

    The script should print output that looks similar to this text:

    Output
    Source files looks good, continuing
    Created backup at ./backup-2021-12-30.zip
    
  5. Using your terminal, create a directory named python-app. In the new directory, create a file called script.py:

    Bash
    mkdir python-app
    cd python-app
    touch script.py
    cd ..
    

    Your directory should now look like this:

    Output
    -| webapp/
    ---| app.js
    ---| index.html
    -| python-app/
    ---| script.py
    -| Backup.ps1
    
  6. In the PowerShell shell, run the script again, but this time change the -Path value to point to ./python-app:

    PowerShell
    ./Backup.ps1 -PathIsWebApp -Path './python-app'
    

    Your script should now print this text:

    Output
    No backup created due to: Not a web app
    

    The output indicates that the check failed. It should have, because there are no files in the directory that have an .html, .js, or .css extension. Your code raised an exception that was caught by your Catch block, and the script stopped early.

    Congratulations! You've implemented a business requirement.


 

 

 

 

 

 

 

 

 

 

Check your knowledge

1. 

Which file extension is correct for a script?

2. 

What's the correct way to declare a required parameter?

3. 

How can you cause a terminating error?

Summary

 

 

 

In this module, you learned how you can use PowerShell to automate tasks by writing and running scripts.

You went on to improve your scripts by using variables and parameters to make the scripts more flexible.

You then learned about flow control, and how you can use it to control how a script is run. You implemented some checks to sanitize input to ensure the script will exit early if certain conditions aren't met. You also added checks to ensure the script carries out its task (backing up files) only if there's no pre-existing backup file.

Finally, you were introduced to error handling. You learned how to differentiate between non-terminating and terminating errors and how to manage both.

You should now have a good understanding of how to write and run scripts. You should also be able to use various PowerShell constructs to improve a script's flexibility and robustness.