Why would I want to call a function that exists in a separate script?

By Jesse Hamrick • January 9th, 2008

Tom MoreauDR. Tom Moreau posed the following question, “Is there a way to call a function that resides in a separate script, along the lines of Perl’s use statement? I don’t want to have to load each function script manually into the current PS session.”

I said sure, take a look at my article on organizing script code and calling functions using dot sourcing.

Tom’s response, “That’s close to what I’d like. Ideally, I’d like to refer to the script name just once and then refer to the functions therein as required. I’m wondering what to do if I have a .PS1 script that contains multiple functions and I want to execute a specific function within that PS1 script.”

What a great idea. To have a PowerShell script that contains multiple functions in which specific functions could be called from other scripts. How do we do this?

Tom came up with the answer and is gracious enough to share with the rest of us. The best way to explain it is to show some examples. First we will create a .ps1 script file that contains the functions we are going to use:

Save the following code as Functions.ps1

function F1 ($a) {Write-Host “Here it is: $a”;}
function F2 ($a) {Write-Host -foregroundcolor yellow “Here it is: $a”;}

Save the following code as TestFunctions.ps1

. C:\MyScripts\Functions.ps1

F1 (”This is a test. “);
F2 (”This is another test. “);

Before running the TestFunctions.ps1 script, note that the script is using dot source to access the Functions.ps1 script file. I’ve used the full path for the location of Functions.ps1. If both scripts are located in the same folder you can shorten your path statement as follows:

. .\Functions.ps1
Function Results

Results

Running the TestFunctions.ps1 script should yield these results:

As expected the TestFunctions.ps1 script ran both the F1 and F2 functions defined in the Functions.ps1 script. Here is where it gets interesting. Let’s say we only want to run the F2 function, we just need to modify the code in the TestFunctions.ps1 script:

. C:\MyScripts\Functions.ps1

F2 (”This is another test. “);

Function Results Modified

Results

Run the TestFunctions.ps1 script again. Does your output look like this?

When I ran these examples provided by Tom, my only thought was “how sick is that!”

Here are some benefits:

  • I can store multiple functions in a single script file and call specific functions when needed. Great way to build and use your code library.
  • I can call functions that I’ve used in other scripts without having to re-write them in a current session.

Again, a big thanks to Tom Moreau for sharing and expanding our knowledge on the possibilities of PowerShell.

Email This Post To A Friend Email This Post To A Friend

These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • Digg
  • Furl
  • Reddit
  • Technorati
  • YahooMyWeb

Comments

Be careful with those parentheses. You don’t use parens to provide parameters to functions or cmdlets, only methods. Parens in the examples above are actually sub-expressions. Luckily, the sub-expression was just a string so it ended up doing what you had planned. Here’s how you can prove that it’s a sub-expression:

F1 (”test”) # output of the sub-expression is the string “test”
F1 ( 2+5 ) # output is the INT 7.
F1 ( dir ) # that would get incredibly messy

Unless you need sub-expressions, it’s best to leave off the parens. The below would just send the corresponding strings to the function.

F1 “test”
F1 “2+5″
F1 “dir”

This doesn’t work…

I could not get the example to work either. I continually get the error is not recognized as a cmdlet, function, operable program or script file.

Any thoughts or ideas? This would be a great tool if I could get it to work.

I tested the code and it is still working.
The reason you are getting “Not Recognized as a Cmdlet, Function…” error is because you are attempting to run the script by just calling the name. Example - PS C:\MySripts>testFunctions.ps1. You need to use dot-notation to run scripts in PowerShell. This is how your command line should look (without the quotes):
“PS C:\MyScripts>.\testFunctions.ps1″
Note the differences between both.
Hope that helps…

By Iain Spirit on August 21st, 2008 at 8:10 am

Scripts work fine.
Really enjoying going through this, time to move on from DOS. Can’t wait for the later chapters!

Hi,
I too am getting the error is not recognized as a cmdlet, function, operable program or script

BUT the system is complaining about the call to the “functions” file when we use the ..\ functions.ps1. It works fine with the . and the fully qualified name but doesnt seem to like the relative path notation
ANy ideas?

Hi,
Ok,i solved the problem.. when not qualifying the full path the line is actually

.(space).\functions.ps1

I was reading it as .. (two dots in succession )

- thanks

What if I wanted a function that returned a value so that I could pass it to another function? Can you show how I would do that?

If you wanted to take it one step further for a Functions library, you could put the file in the PSHome dir (usually “C:\WINDOWS\system32\WindowsPowerShell\v1.0″ or look at $PSHome) and then you would only have to use “. Functions.ps1″ w/o the quotes, of course, and don’t forget the space after the ‘.’ Hope that helps.

It broke up my example…it would be
“. Functions.ps1″ (w/o the quotes)

Yesm hte “. .” thing was stoping me to call the functions. Putting it this way will keep the context open and the functions will remain visible.
Thanks Benjy!

and thatnks for trying to explain to the author.

By phghost on May 8th, 2009 at 2:08 pm

Gracias me ha servido de mucho!!!

By Chris Allen on July 24th, 2009 at 7:18 am

I would like to use dot sourcing to pull from a list of functions, but I would also like to be able to run the script with external parameters. Normally, functions have to be declared at the top of the script as does your Param() statement. These seem to compete with each other. The one that is at the top wins, the other is either ignored or produces an error.

So, If I wanted to pass a parameter into a script (I.E. .\test.ps1 -lanid dude123) how would I be able to use that and still dot source my functions?

. C:\MyScripts\Functions.ps1
Param($lanid)

By Chris Allen on July 24th, 2009 at 7:27 am

Never mind. I figured it out. With dot sourcing, the functions do not have to be absolute top of the script.

As a test, I created the function file below with a simple get-mailbox shortcut called getMB.

Then created a script called test.ps1 which looks as follows:

Param($lanid)
. C:\MYScripts\Functions.ps1
getmb $lanid

Putting the Param before the dot source call works perfectly. I ran .\Test -lanid dude123 and it returned the proper results.

By Chris Allen on July 24th, 2009 at 10:13 am

Ok, I do have a question after all.

Is it possible to call a dot source file from a UNC?

By Mostafa Mokhtar on October 14th, 2009 at 6:12 pm

Hi

I wanted to know how to call powershell functions that I wrote asynchronously?
any ideas?

 

Leave a Comment

« Download PowerShell 2.0 Community Technology Preview (CTP) | Home | How to retrieve a list of Computer Accounts from Active Directory »