PowerShell: Use a Function to Create a Variable

Anyone who has worked with PowerShell for more than five seconds knows (or anyone who hasn’t but has done any programming can probably guess) that creating a variable in PowerShell is simple:

$animal = “cat”

Amazing! You now have a variable that is equal to the string “cat”. So, if it is that simple, why on earth would you need a fancy and dandy function to do that for you? I can probably give a better reason in the post to follow, but to make it simple, what if you want a script to generate a reusable variable on the fly? The situation where this was applicable to me was while writing a script that needed to create several objects with very similar properties. If I wanted to create three objects, here might be the code:


$car1 = New-Object System.Object

$car1 | Add-Member -type NoteProperty -name Year -value 2009

$car1 | Add-Member -type NoteProperty -name Make -value "Chevrolet"

$car1 | Add-Member -type NoteProperty -name Model -value "Camaro"

$car2 = New-Object System.Object

$car2 | Add-Member -type NoteProperty -name Year -value 2011

$car2 | Add-Member -type NoteProperty -name Make -value "Ford"

$car2 | Add-Member -type NoteProperty -name Model -value "Mustang"

$car3 = New-Object System.Object

$car3 | Add-Member -type NoteProperty -name Year -value 1979

$car3 | Add-Member -type NoteProperty -name Make -value "Chevrolet"

$car3 | Add-Member -type NoteProperty -name Model -value "Impala"

Isn’t that rather repetitive and needlessly long? What if we could instead create a function that would reduce the above code to this:


New-Car "car1" 2009 "Chevrolet" "Camaro"

New-Car "car2" 2011 "Ford" "Mustang"

New-Car "car3" 1979 "Chevrolet" "Impala"

That would be so much quicker, easier to read, and just plain efficient. The idea is simple. You create a function that accepts input for the new object/variable’s name, the year, make, and model. The tricky part comes in when you try to get a function to create a variable based on the string value of another variable. How do you use ($varName = “car1”) to create the variable $car1?

You might think you could do something like this:


$varName = "car1"

$varName = "$" + "$varName"

At this point, $varName does equal “$car1”, but only as a string value. If you try setting the value of $car1 inside a function by using something like “$varName = New-Object System.Object” you are turning $varName into an object, not $car1. “Aha!” you might say, “I can put parenthesis around $varName!” Seems logical. In theory, “($varName) = New-Object System.Object” would render as “$car1 = New-Object System.Object”. Except that you may remember $varName only contains the value “$car1”, which is a string, not a variable. Now what?

Enter Set-Variable…

When you create a variable using Set-Variable or New-Variable, you do not name the variable with the traditional “$” in front. for example:


$color = "green"

is the same as

New-Variable -name color -value "green"

Both lines create the variable “$color” with the value “green”. How is this helpful? Consider the following:


Function New-Var ($name,$value){

New-Variable -name $name -value $value -scope script

}

New-Var color "green"

The “New-Var” function has just created the variable “$color” with the value “green”. And, because the variable scope is set to script, you can call and manipulate the new variable outside the function:


New-Var color "green"

If ($color -notlike "red"){$color = "red"}

Write-Host $color

Thrilling, right? Maybe not yet. So far, all we have done is create a function that takes a lot more time than using built-in functions to perform a very basic task. However, this truly becomes a handy trick when working with similar objects that contain multiple members, or properties. What will our New-Car function look like?


Function New-Car ($name,$year,$make,$model) {

New-Variable -name $name -value #Oh no! What do we put here without resorting to an array?

}

The New-Variable and Set-Variable cmdlets don’t readily lend themselves to adding on bits and pieces to an object. The easy way around this? Create a temporary object inside your function that will become the value of the resulting variable:


Function New-Car ($name,$year,$make,$model) {

$object = New-Object System.Object

$object | Add-Member -name year -type NoteProperty -value $year

$object | Add-Member -name make -type NoteProperty -value $make

$object | Add-Member -name model -type NoteProperty -value $model

New-Variable -name $name -value $object -scope script

}

Et voila! We create the object, give it the values we want to use for “$car1”, and then use the variable $object as the value for New-Variable. Note the “scope” in the New-Variable cmdlet. This is important if you want to manipulate or use the $car1 variable outside the function. And, after all, that is the only reason we would want to go through this mess.

Now that we have written this nice function that creates a variable based on the name and values we pass through as parameters, we can simplify our code to this:


New-Car car1 2009 "Chevrolet" "Camaro"

New-Car car2 2011 "Ford" "Mustang"

New-Car car3 1979 "Chevrolet" "Impala"

New-Car car4 1999 "Ford" "Escort"

New-Car car5 2007 "Kia" "Rio"

There you have it. 20 lines of code reduced to 5. And isn’t that easier to read. All thanks to using a function to create a variable.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s