Read-Only and Constant Variables

Quick reminder: You can make variables in PowerShell read-only, or constant.

I’ve written about this before, but it’s time to cover it again for any newcomers to PowerShell, and because I actually found a need for it. Previously, it was just pure learning and sharing. Today, I’ll let you in on how I recently used a read-only variable, and bonus, something else I discovered, too! Let’s begin with how to use these variable options.

When you’re new to PowerShell, you learn to create variables by using the assignment operator. No, not the equals sign. Look at the below example, and then say it out loud as, “ADUser (or dollar sign ADUser) is assigned the values returned by the Get-ADUser Cmdlet.” Don’t say equals; it’s not equals. Lose that habit, if you have it. And yes, people will be listening for it. Okay fine. It may just be me.

You can also create a variable and assign it a value by using the New-Variable Cmdlet. Notice that we don’t use a dollar sign when we do it this way. The same goes for all of the *-Variable cmdlets (Get-Command -Name *-Variable). Dollar signs aren’t a part of a variable, as much as they’re there to indicate to the parser, that what follows a dollar sign, is a variable. That’s how I’ve come to understand it, anyway.

We can use Set-Variable to reassign our previously existing variable. If we use Set-Variable against a variable that doesn’t already exists, it essentially runs New-Variable. It may actually run New-Variable.

Now, one last piece of information before we move on. New-Variable (as well as Set-Variable), has an Option parameter. It’ll accept a handful of predetermined arguments, or parameter values, but today we’ll cover the ReadOnly value. We’ll touch on the Constant value, too. A read-only variable is one where you can’t change the value after the variable has been assigned. Okay, that’s not entirely true. You can reassign a read-only variable if you use the Force parameter. If we use Constant instead of ReadOnly for the Option parameter’s value then there would be no way to reassign the variable ever. Additionally, you can only make a variable a constant when it’s first created. That’s pretty much the difference between those two.

I have what I’ve written and called, the Advanced Function Template, for work. I won’t go into all the neat things it includes, but a few years later and I’m still quite proud of all the things I’ve stuffed into it. I use it as my starting point for every function I author. One thing it does is logging (to the screen, to a file, or both). As a part of its logging, it lists the block location. Here’s an example of a function created with the template (that has no, non-template code logging, at minimum).

Okay, “Info” and “Param” aren’t block locations like Begin, Process, and End. Even so, I’ve found them to be helpful. This value is stored in the $BL variable originally, and, as you can see, the value is changed while a function is executing. It occurred to me recently, and randomly, that someone else that builds a tool from this same function template might create their own BL, or bl (it doesn’t matter) variable. This would cause a mess! This whole thing would be better if the variable were protected: enter the variable read-only option. While I could’ve made it a constant, the function (my code) wouldn’t be able to change its value, but you knew that already.

So, I changed all my $BL variable assignments to these, which are a part of the template function code now.

Now, if a function author uses my function template and without knowing they shouldn’t, tries to create a variable using $BL, they won’t break what the function template is doing in the background. PowerShell will put a stop to that before they get too far (without making the function template explode). Here’s how it appears in my testing; this should look familiar.

Now, I’m going to need to consider the nested functions in the function template and their protection, too. It would be less likely they’d choose the same name of those, but I’m of the mindset that we should put in protection even if we don’t think we’ll need it.

Oh, last thing (but not really). I had this thought: Can I make a preference variable read-only?

I can! I can see where this may be helpful for my function template, too!! I didn’t bother trying it, but this variable likely can’t be made to be a constant. This option has to be applied at the time a variable is created, unlike read-only, which can be applied to a variable after it’s already been created. Important note, to which I implied earlier.

And finally, in case you cared to see the first, Active Directory example in this article using New-Variable, then here you go. It works like Math. You know, Order of Operations: complete what’s in the parentheses first, and then continue. If you didn’t include the parentheses, it would make Get-ADuser a string and assign it as the value of the ADUser2 variable. Then, it would fail when it thought, you thought the New-Variable Cmdlet had an Identity parameter. Uhhh, no.

≥ Tommy Maynard (Twitter: @thetommymaynard)

About Tommy Maynard

IT Pro. Passionate for #PowerShell, #AWS (certified x2), & all things automation. I'm not done learning. Author in #PSConfBook. Writes at