How Do I Use a Windows PowerShell Script Containing Functions?


Summary: Using a script containing Windows PowerShell functions can be as simple as dot-sourcing the script.


Hey, Scripting Guy! Question

Hey, Scripting Guy! I was looking in the Script Center Script Repository for Windows PowerShell scripts, and I found one that was really cool. Unfortunately, when I attempted to use it, it did not work. I know that scripts in the Script Repository are not supported, and I am not asking you to fix the script, but I need to make sure I am using the script properly.

— OM


Hey, Scripting Guy! Answer

Hello OM,

Microsoft Scripting Guy Ed Wilson here. It seems that every year some business consultant writes a book that becomes “the book” for businesses during that calendar year. I remember one book about sharks, and before that a book about a carpet salesperson. The books themselves are generally innocuous, but the violence inflicted upon “corporate speak” is often irreparable. A brief stroll down the corridors of any Fortune 500 company should be long enough to sample the drivel of “putting skin in the game,” “seeking win-win solutions,” or “finding an end game strategy.” While it appears that many of the tortured phrases are “leveraged” from athletic contests, some are more pedestrian if not downright mundane. Consider the moniker “elevator pitch” that I assume replaces the now semi-pejorative “executive summary.”

OM, a “30,000-foot view” (perhaps now updated to 40,000-foot view with reference to the higher altitudes the airlines are flying in attempts to reduce fuel costs) of Windows PowerShell might consist of the following: “Windows PowerShell is both a scripting language and an interactive command environment. It is as if Microsoft took the old-fashioned command prompt, and put VBScript inside it.”

It is this dual nature of Windows PowerShell—the scripting and the interactive environment—that confuses people when they first begin to “leverage PowerShell for their network automation solution” (ugh—sorry about that). Windows PowerShell 2.0 mitigates this confusion a little because there is the Windows PowerShell console, and the Windows PowerShell ISE (integrated scripting environment—a script editor). I open the Windows PowerShell console when I want to work in an interactive fashion, and I open the Windows PowerShell ISE when I want to write, edit, or run a script. Of course, you can run Windows PowerShell scripts from within the Windows PowerShell console, but I often prefer to open the script in the ISE so that I can peruse the code the script is executed, especially if it is one with which I have not recently worked.

Windows PowerShell contains a number of little programs called cmdlets (pronounced “command lets”). I obtain a list of the cmdlets by using the Get-Command cmdlet and specifying the CommandType of cmdlet. The command shown here produces the output displayed in the image following it:

Get-Command -CommandType cmdlet

Image of output of Get-Command cmdlet

To use one of these cmdlets can be as simple as typing the cmdlet name and pressing ENTER, or as complex as supplying multiple values for numerous parameters (for example, to obtain a list of all the services on the workstation using Get-Service). The command Get-Service produces the output shown in the following image.

Image of output of Get-Service cmdlet

The scripting language aspect of Windows PowerShell allows one to use things such as for/next; however, in Windows PowerShell language, it is simply the for statement because there is no next. To produce a list of numbers from 1 to 10, you could use code such as this:

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

By adding additional information in the script block (the curly brackets), the output is modified. The following image shows the output.

Image of modified output

OM, you may be asking what this has to do with running a script found in the Script Repository. Suppose you find a script named Add-Numbers.ps1 that contains a single function called Add-Numbers. The function accepts two numbers and returns the sum. The following image shows the content of the function.

Image of content of function

When I run the Add-Numbers.ps1 script, nothing happens. If I use the dir command (an alias for the Get-ChildItem cmdlet), I can confirm that absolutely nothing did in fact happen. If I dot-source the script (by placing a period and a space on the line in front of the path to the script), and then I use the dir command to check the function drive, I can see that the Add-Numbers function was added to the function drive. This allows me to use the function in the same manner that I use Windows PowerShell cmdlets. The following image illustrates this technique.

Image of checking to see if Add-Numbers function can be used in same manner as cmdlets

In modifying the script to contain code that will run when the script launches (also known as directly executable code), you will see output when the script runs. The revised Add-Numbers.ps1 script adds command-line parameters, and calls the Add-One function with values supplied by the command-line parameters. I assign default values for the two command-line parameters because it is often desirable for a script to run without user intervention. The revised script is shown here.


Param($intOne = 5,
$intTwo = 3
Function add-numbers
$intOne + $intTwo
} #end function add-numbers
# *** entry point to script ***
add-numbers -intOne $intOne -inttwo $intTwo

Most of the scripts I write contain directly executable code with judiciously selected default values. This allows a person to run a script with no intervention. If you deploy a script such as a logon script using Group Policy, you do not want the user to be bothered with questions. You want the script to run in an unattended fashion. I will talk about using Group Policy to run a logon script in this coming Saturday’s Weekend Scripter article.

When running the Add-NumbersWithExecutableCode.ps1 script, the two default values are used, and the number 8 appears on the Windows PowerShell console. Because the script creates command-line parameters, it accepts different values when it launches. You can use the parameter names or positional arguments. All this is groovy. As before, the function does not appear on the function drive. The problem with executable code arises when the script is dot-sourced into the Windows PowerShell console. The following image illustrates the problem—the executable code launches using the default parameter values, and the number 8 appears on the Windows PowerShell console. However, the good news is that the function resides on the function drive and is available for additional use.

Image of proof function is available for additional use

It is therefore up to the person who writes the script: Include only functions, or add additional code that permits independent execution of the script? The decision point is the use case scenario for the script—how will you normally use the script?


OM, that is all there is to using a script that contains a function at the Windows PowerShell console. Running Windows PowerShell Scripts Week will continue tomorrow when we will talk about using functions in scripts.

We invite you to follow us on Twitter or Facebook. If you have any questions, send email to us at or post them on the Official Scripting Guys Forum.. See you tomorrow. Until then, peace.


Ed Wilson and Craig Liebendorfer, Scripting Guys