PowerShell How-To

When and Why To Convert a Script into a Function

And when converting, remember that reusing code will save you a ton of time.

As a beginner to writing scripts with PowerShell, you won't learn the concept of a function until later. Newbies typically learn about PowerShell functions after they've learned what the pipeline is, how cmdlets work and how to accomplish some basic tasks. Functions aren't typically learned until later -- not because they are less important, but because a scripter technically doesn't even need functions at all to write scripts that work. Functions are created by scripters who have earned their newbie stripes and yearn to get to the next level of expertise.

I mentioned earlier that functions are not technically required. This is true, but -- depending on the script -- the lack of functions could take what is considered a well-thought-out, useful script and turn it into an amorphous mess of code that only works in a single instance, and only when everything is just right.  Make one small tweak, and the entire script could bomb.  These types of scripts technically work, but they're far from what we would consider a well-written script.

With that being said, how would someone prevent their script from turning out so badly? The solution is to use functions (when required). The first question we need to ask is, "If functions are so important, how would I know when to create one, anyway?" The answer is simple: When the code needs to be reused, or when it may need to be reused at a later time. Functions are all about code reuse, and they're created to prevent code like the following:

if (Test-Connection -Computername ‘COMPUTER1' -Quiet -Count 1) {
Add-Content -Path ‘C:\MyFile.txt' -Value ‘COMPUTER1'
}
if (Test-Connection -Computername ‘COMPUTER2' -Quiet -Count 1) {
Add-Content -Path ‘C:\MyFile.txt' -Value ‘COMPUTER2'
}

That's three lines of code to test whether a computer can be pinged and then to add it to a text file.  I'm only adding two computers here, but what if I have 10?  That'd be 30 lines of code.

Now, let's create a function and do the same thing.

function Add-ComputerToTextFile ($Computer) {

if (Test-Connection -Computername $Computer -Quiet -Count 1){

Add-Content -Path ‘C:\MyFile.txt' -Value $Computer }    }
@(‘COMPUTER1','COMPUTER2') | foreach {Add-ComputerToTextFile $_}

That's still six lines of code, but that's a maximum of six lines of code -- regardless of whether I have six computers or 600.

The trick to figuring out if you need a function is to spot repeating patterns in your code. In the last instance, I noticed I was doing the exact same two actions on a single computer: pinging it and adding it to a text file. Soon after you begin noticing these natural patterns, you'll be able to prevent duplicating code at all. You'll immediately see these opportunities before writing the duplicate code.

Here's another example.  I have a user in Active Directory, and I first need to check to see if his username matches a specific pattern. If it does, I need to write some attributes of this user account into a text file for later research.  Can you tell if I should create a function from this?

$Username = (Get-AdUser -Filter {givenName -eq 'Adam' -and surname -eq 'bertram'}).samAccountName

## Check to see if the username is first initial/last name

if ($UserName -match ‘ABertram') {

    Add-Content -Path ‘C:\AdUsers.txt' -Value ‘abertram'

}

The answer is yes. "But there's no duplicate code," you say? True. However, how likely are you to perform a task like this on another username or on many different usernames?  If you think to yourself that it's even remotely likely, then it should be a function.

Here's what it should look like:

function Test-Username ($FirstName,$LastName) {

$Username = (Get-AdUser -Filter {givenName -eq $FirstName -and surname -eq $LastName}).samAccountName

## Check to see if the username is first initial/last name

$FirstInitial = $FirstName.SubString(0,1)

if ($UserName -match “$FirstInitial$LastName”) {

    Add-Content -Path ‘C:\AdUsers.txt' -Value $Username } }

Test-Username -FirstName ‘Adam' -LastName ‘Bertram'

In this instance, I am sacrificing a few lines of code for reusability. You can see that the decision regarding when to use functions isn't just about the number of lines of code saved. This is sometimes a beneficial byproduct of reusability, but not always.

The key to spotting when to create a function in a script is to be thinking ahead all the time. Begin asking yourself, “Today this code works, but what if tomorrow I need to perform this same task a hundred times? What would it take for me to modify this code to work with other components of the script? Will I have to change 15 lines just to make a minor adjustment?” These are great questions to ask yourself if you're ever wondering if there might be a better way to write code.

If you only remember one thing from this article, remember the words code reuse, as this is the major premise behind building functions. Functions aren't the only concept behind making code more reusable, but they are one of the biggest.

About the Author

Adam Bertram is an independent consultant, technical writer, trainer and presenter. Adam specializes in consulting and evangelizing all things IT automation mainly focused around Windows PowerShell. Adam is a Microsoft Windows PowerShell MVP, 2015 powershell.org PowerShell hero and has numerous Microsoft IT pro certifications. He is a writer, trainer and presenter and authors IT pro course content for Pluralsight. He is also a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at adamtheautomator.com or on Twitter at @adbertram.

comments powered by Disqus

SharePoint Watch

Sign up for our newsletter.

I agree to this site's Privacy Policy.