- The Operation Validation Framework: Test your infrastructure using Pester - Mon, Jun 25 2018
- How to write an Azure Function in PowerShell - Tue, Jun 12 2018
- Process file paths from the pipeline in PowerShell functions - Mon, Jun 4 2018
By default, PowerShell is pretty lenient with certain programming rules that are considered bad practice. This can be both a blessing and a curse: a blessing in that it allows some flexibility when developing a script or learning PowerShell for the first time, but a curse in that certain classes of bugs and poor design choices can creep into your code and make troubleshooting a nightmare. Leaning how and why to use Strict Mode will help you level-up your PowerShell development skills and stamp out those pesky bugs.
Introduction
So, what is PowerShell’s Strict Mode? Essentially, Strict Mode disables a few programming rules that PowerShell normally lets us use that go against best practices. Coding with these best practices in mind can help prevent bugs in your script at the cost of a little flexibility, especially during development. When Strict Mode is enabled, violating these rules will produce terminating errors in our scripts. Using the cmdlet Set-StrictMode, Strict Mode can be set to the following:
- Off
- Version 1.0
- Version 2.0
- Version Latest
This is a very simple cmdlet as far as parameters go. We only have two parameters to work with, Off and Version.
# Disable strict mode Set-StrictMode -Off # Set strict mode to version 1.0 Set-StrictMode -Version 1.0 # Set strict mode to version 2.0 Set-StrictMode -Version 2.0
When Strict Mode is set to Off (the default state), PowerShell operates with the most lenience and flexibility.
Setting Strict Mode to Version 1.0 will prohibit you from referencing variables that have not been initialized.
Strict Mode to Version 2.0 will also prohibit you from referencing initialized variables, in addition to prohibiting references to non-existent properties on objects, function calls using the syntax for calling methods, and variables without names.
When Strict Mode is set to Version Latest, it’ll use the strictest version available. This is currently Version 2.0, but if a newer version is added to PowerShell in the future, this setting would automatically use that newer version instead of Version 2.0.
When Strict Mode is enabled, it affects the current scope, and any child scopes. This means that if a PowerShell script or module turns on Strict Mode, it won’t affect the global scope, nor will it break other scripts or modules that aren’t children of the scope where it was set.
Now let’s dive a little deeper into what these rules mean, and take a look at some examples.
Strict Mode version 1.0
You can enable Strict Mode version 1.0 by running:
Set-StrictMode -Version 1.0
Version 1.0 prohibits referencing uninitialized variables. In practice, this looks like:
Set-StrictMode -Off $foo Set-StrictMode -Version 1.0 $foo
You can see that with Strict Mode turned off, PowerShell has no problem with us referencing a non-existent variable, but will pitch a fit when Strict Mode is set to Version 1.0.
Strict Mode version 2.0
You can enable Strict Mode version 2.0 by running:
Set-StrictMode -Version 2.0
On top of what Version 1.0 disables, Version 2.0 also prohibits us from referencing non-existent properties on objects, calling functions using the syntax for calling methods, and using variables without names.
I’d argue that referencing uninitialized variables and non-existent properties on objects are much more common than the latter two rules.
Referencing non-existent properties on objects is a common bug you’ll encounter when developing PowerShell scripts or modules, and will lead to a fair amount of hair pulling. Since everything in PowerShell is an object, we tend to make many references to properties of those objects, meaning typos are inevitable. Setting Strict Mode to Version 2.0 will cause them to produce a terminating error rather than nothing at all:
Set-StrictMode -Version 2.0 $myObj = [PSCustomObject]@{ Property1 = 'foo' Property2 = 'bar' } $myObj.Property1 $myObj.Propery2
Now, let’s look one of these lesser-known rules. Strict Mode version 2.0 prohibits calling functions using method syntax:
Set-StrictMode -Off function Add-Numbers { param( $Num1, $Num2 ) $Num1 + $Num2 } Add-Numbers(32, 10) Set-StrictMode -Version 2.0 Add-Numbers(32, 10) Add-Numbers -Num1 32 -Num2 10
Without version 2.0 Strict Mode enabled, PowerShell will treat (32,10) as an array, and pass to the first parameter (Num1). Num2 will not have a value so nothing will be added. I personally have not seen this syntax used in the wild, but it is certainly a possibility, and a bad practice nonetheless.
Subscribe to 4sysops newsletter!
Conclusion
As demonstrated in these examples, using PowerShell’s Strict Mode can help eliminate several potential sources of bugs in your code. When developing a new script or module, it’s a good idea to put Set-StrictMode right at the top to help nudge you toward using the best practices and save you some troubleshooting and stress down the road.
I have
Set-PSDebug -Strict
at the start of my $Profile, which is pretty much the same as
Set-StrictMode -version 1.0
(I used Set-PSDebug because I didn’t know about Set-StrictMode back then 🙂 )
This has saved me significant amounts of time that I used to waste tracking down mis-typed variable names. After reading the article I’ve updated $Profile to use strict mode version 2.0, that’ll help out even more.+
To the readers: Check out Set-PSDebug if you haven’t – it can be set to display variable assignments, function calls, etc when the script runs. Sometimes too much information is presented, but if you have a problem code section, turn it on for that section then turn it off afterward until you get the kinks worked out.
If you are completely honest, how many of your scripts actually start with Set-StrictMode?
Set-Strictmode is a great theoretical idea, and I would probably use it if I could choose what I was strict about, but there is a reason why no scripts on the technet gallery uses it, even from people who otherwise recommend using Set-StrictMode…
I was curious, so I downloaded a bunch of scripts from various”professional powershellers” (I think they are at least), and not one of the scripts had it.
Hi Lars,
please check this out.
https://gallery.technet.microsoft.com/scriptcenter/Gets-the-Reliability-d3226154
is only to use during the development phase.