Download as pdf or txt
Download as pdf or txt
You are on page 1of 12

Live Cyber Attack Lab 🎯 Watch our IR team detect & respond to a rogue insider trying to

steal data! Choose a Session 

SUPPORT COMMUNITY SERVICES 1-877-292-8767 SEARCH

PowerShell Variable
Scope Guide: Using
Scope in Scripts and
Modules
POWERSHELL

Inside Out Security Blog » PowerShell » PowerShell Variable Scope Guide: Using Scope in Scripts
and Modules

BY

JEFF

 BROWN UPDATED: 3/18 /2021

PowerShell uses variables to store information that can be useful later on. Variables also make it
easy to change values in multiple places by changing the variable’s definition. You can store
information such as names, paths, and the results of commands in a variable.

As you become more fluent in PowerShell, the idea of variable scope is likely to start playing a part
in writing scripts, functions, and modules. In this post, I will cover the basics of PowerShell variable
scope and provide examples of how to use scoping in PowerShell scripts and modules.

Get the Free PowerShell and Active Directory


Essentials Video Course
First Name* Last Name*

First Name Last Name

Email*

Email

I agree to receive communications from Varonis.*

You can unsubscribe from these communications at any time. For more information on
our privacy practices, and how we're committed to protecting your information, please
review our privacy policy.

Get Started Now

I'd recommend this for both new and advanced PowerShell users.
Building an AD tool is a great learning experience.

In addition to mastering scope, you can check out a collection of PowerShell tools for additional
resources like editors, modules, and training to take your PowerShell skills to the next level.
What are PowerShell Scopes?

PowerShell scope protects variables and other artifacts by limiting where they can be read and
modified. Scope levels protect items that should not be changed. PowerShell has the following
scopes available:

Global: This scope is available when you open a PowerShell console or create a
new runspace or session. PowerShell’s automatic and preference variables are
present and available in the global scope. Any variables, alias, and functions
defined in your PowerShell profile are also available in the global scope.

Script: This is the scope created when you run a script. Variables defined in the
script are only available to the script scope and not the global or parent scope.

Local: This is the current scope of where a command or script is currently running.
For example, variables defined in a script scope is considered its local scope.

Private: While not technically a scope, using private can protect a variable’s visibility
outside of the scope where the variable is defined.

Scopes work in a hierarchy, meaning global is the parent scope. Variables defined in the global
scope are automatically available to the child scope for viewing. However, variables defined in the
child scope are not available to the parent scope.

PowerShell scoping follows a few basic rules:

Scopes nest with each other. The outer scope is the parent scope, and any nested
scopes are child scopes of that parent.
An item is available in the scope where it is defined and to any child scopes unless
explicitly made private.

An item created in a scope can only be changed in the scope it was defined.
Another item with the same name in a different scope may hide the original item,
but it does not override or modify the original item.

Global Scope vs. Script Scope


Let’s take a look at some examples of different scopes in action. I have a script that defines a
variable and outputs it to the screen:

1. $greeting = “Hello, World!”

2. $greeting

This script defines the variable $greeting in the script (or local) scope. However, that variable and
its value will not be available to the PowerShell console, which is the parent scope. Examine the
output of the PowerShell commands here:

I display the $greeting variable’s current value in the console (or global scope), and, as expected, it
is empty. I run the script file where $greeting is defined and outputted to the screen. Once the
script exits, I display the value of $greeting again in the PowerShell console, and it is still blank. This
behavior is expected as the $greeting variable is in the child script scope and not in the parent
global scope.
Let’s examine the reverse of this. Instead of defining the value of $greeting in the script, let’s define
it in the global scope. The script then displays the value of the $greeting variable inside the script
as it inherited it from the global scope.

Inside the script, I did not set or modify the $greeting variable. I only displayed its value. The
greeting string was inherited from the console as the parent scope by the script file as the child
scope.

Using Scope Modifiers


In the previous examples, we see how a variable defined in the child script scope was not available
to the global scope for reference. However, we can use scope modifiers to change the scope of
the defined variable. A few scope modifiers include:

Scope Modifier Usage

global: The variable exists in the global scope

local: The variable exists in the local scope

private: The variable is only visible in the current scope


script: The variable exists in the script scope, which is the
nearest script file’s scope, or Global if one is not
available

For example, I can use the $global: prefix on a variable inside a script to change a variable value
that I have already defined in the global parent scope. Examine the script and console output
below:

I defined the $greeting variable in the global console scope as “Hello, Jeff!”. I then ran the script
file, which reassigned the value to “Hello, World!” using the $global: scope modifier. After running
the script, the value of $greeting has been modified in the global console scope to the script’s
value.
Using Scopes in a PowerShell Module
A PowerShell module is a package of commands, such as cmdlets or functions, that have similar
functions or purposes. An example of this is the ActiveDirectory module for Windows PowerShell,
which contains commands to manage Active Directory objects.

You can author a module yourself and may need to reference the same variable in different
functions. By setting variables using the script scope in a module, the variables are now shareable
between the module’s functions.

Here is an example PowerShell module file (MyModule.psm1) that contains two functions, Get-
Greeting and Set-Greeting:

1. function Get-Greeting {
2. if ($name) {

3. $greeting = "Hello, $name!"

4. }
5. else {

6. $greeting = "Hello, World!"

7. }

8.
9. $greeting

10. }

11.
12. function Set-GreetingName {

13. param(

14. [Parameter(Mandatory)]
15. [string]

16. $GreetingName

17. )

18.
19. $name = $GreetingName

20. }

Note that both functions reference the $name variable. However, since I defined the variable in
separate functions, they are scoped only to that function. Setting the $name variable in the Set-
GreetingName function does not affect the $name variable in Get-Greeting. You can try this
yourself by saving this code to a .psm1 file, importing it using the Import-Module command, and
referencing the module filename.

Even though I set the $name variable using the Set-GreetingName function, this did not affect the
$name variable in the Get-Greeting function. Each $name variable is scoped to its own function. If I
change the value in one function, it does not affect the other function.

If I wanted to scope the variable to be available to all functions in the module, I add the $script:
modifier to the $name variable, like this:

1. function Get-Greeting {
2. if ($script:name) {

3. $greeting = "Hello, $script:name!"

4. }

5. else {
6. $greeting = "Hello, World!"

7. }

8.
9. $greeting

10. }

11.
12. function Set-GreetingName {

13. param(

14. [Parameter(Mandatory)]
15. [string]
16. $GreetingName

17. )

18.
19. $script:name = $GreetingName

20. }

If I re-import the module using the -Force parameter, I can now set the value of $name in one
function and reference it in another.

Note how calling Get-Greeting shows the default message as the $script:name variable did not
have a value. After calling the Set-GreetingName function, the Get-Greeting now displays a
different value based on the name I passed. This behavior is expected as both functions are now
referencing the same variable.

While the example module is simple, you can see how this can be useful. I use this functionality to
set API credentials that multiple functions use in modules I write. Check out an example in my twilio-
powershell-module GitHub repository.

Scoping with Dot Source Notation


As I’ve demonstrated in the examples above, scripts and functions will have their own scope
outside the global scope. Changes to variables are only affected in that scope unless you use a
scope modifier to change the variable’s scope.
However,  you can incorporate the scope of a script or function by using dot source notation. When
the script runs in the current scope, any script variables are available in the current scope. You can
use dot source notation by placing a dot/period (.) and a space before the script name. Examine the
script file and code below:

Initially, the value of $greeting in the global console scope is empty or null, and the scopetest.ps1
file sets the value of $greeting. By using dot source notation, the script brings the variable value in
the parent scope. You can also use the call operator/ampersand (&) to run a script or function, and
its scope will not be added to the current scope.

Additional Resources
Understanding scoping in PowerShell is essential when writing scripts, modules, and functions. You
might run into a scenario where a variable has an unexpected value, and this could be due to the
variable inheriting from another scope. Using other techniques such as module-level scoping and
dot source notation can help you build valuable PowerShell tools for your toolbelt.

For more information on writing PowerShell scripts, check out Jeff Petter’s Windows PowerShell
Scripting Tutorial for Beginners.
JEFF BROWN
Jeff Brown is a cloud engineer specializing in Microsoft technologies such as Office
365, Teams, Azure and PowerShell. You can find more of his content at
https://jeffbrown.tech.

——— RELATED POSTS ———

POWERSHELL

How to Install and Import Active Directory PowerShell Module

INCIDENT RESPONSE, POWERSHELL, THREAT DETECTION

Threat Update 46 – Ransomware Early Warning: Data Discovery

POWERSHELL

Git Branching and Merging: A Step-By-Step Guide

POWERSHELL

How to Merge in Git: Remote and Local Git Repositories Tutorial

 
Does your cybersecurity start at the heart?
Get a highly customized data risk assessment run by engineers who are
obsessed with data security.

SCHEDULE NOW

SOLUTIONS PLATFORM COMPANY RESOURCES PARTNERS

Français Remediation How It About Free Technology


Deutsch & Works Varonis Security Partners
日本 Governance How to Buy Varonis Life Training Channel
語 Security How to Use Careers Analyst Partners
P усский Analytics It Customers Reports Partner
PortuguêsData Real Investor Whitepapers Portal
Classification Results Relations Guides
Ransomware ROI Brand Videos
Insider Integrations Contact Us Events
Threats
External
Threats

© 2021 Inside Out Security | Policies | Certifications

You might also like