Prof. Powershell

Breaking Down PowerShell's Scope

Prof. PowerShell visits a beginner topic that many could use a brush-up on.

One constant about PowerShell is that someone is always learning it. So I shouldn't be too surprised to get e-mails or tweets about beginner topics. It helps remind me that Prof. PowerShell needs to revisit some key concepts from time to time. One such topic is scope.

When you execute a PowerShell command, it is running in a particular scope, or container. In PowerShell you will come across a hierarchy of scopes. At the top is the global scope. Think of this as the console with your PowerShell prompt. You probably already know that when you create something like a variable or PSDrive in your session, it doesn't persist, unless you recreate it in your PowerShell profile. That's because when the global scope ends, anything you created in it ends.

This hierarchy continues down to a script scope and then to the function scope. If you have a nested function, then that is yet another scope. Again, anything that you define in a given scope goes away when that scope ends. So if you create a variable in a function, that function ceases to exist when the function ends and you won't see it in the script or global scope unless you take extra measures which I'm not going to cover now.

But one thing I am going to cover that is scope related is dot sourcing. I often will get e-mails that someone downloaded a script from my blog that defined a function but nothing happens when they run the script. They might download something like this:

#requires –version 3.0
Function Get-OS {
Param(
[string]$Computername=$env:computername
)

Get-WMIObject –class win32_operatingsystem –computername $computername |
Select PSComputername,@{Name="OS";Expression={$_.caption}}
} #end function

They will run the script and wonder why nothing happens. This is because the script defines the function, but as soon as the script ends, the scope goes away as does the function. You could call the function within the script but you would need to edit the script every time you wanted to query a different computer.

Instead you need to dot source the script like this:

PS C:\> . c:\scripts\get-os.ps1

You have to be careful here. At the prompt there is a period (.) which is the dot in dot sourcing. It tells PowerShell, "leave your stuff here." Then you need a space followed by the path to the script file. The script runs, defines the function and leaves it in the global scope. Now you can run it.

PS C:\> get-os

What trips people up is when they are in the same folder as the script. Because you always have to specify the path to the script file, this means another period in your expression.

PS C:\Scripts> . .\get-os.ps1

It is easy to miss the first period or the space.

So if you have a script file that defines something like a function, but you never see it called or you want to make it available in your PowerShell session, scope it out and dot source it.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular