When I started writing scripts in PowerShell, I made loads of mistakes as a result of being poisoned by other languages, especially C#, which I work with every day. After a while, I realized that PowerShell has many more similarities with JavaScript than with C#, since it’s an interpreted, weakly typed language. And some time later, I learned that I could write PowerShell in a way that’s closer to TypeScript.
I’m explaining it like this because this parallel is easier for my brain. When I’m programming in PowerShell, it’s much easier for my brain if I’m wearing my TypeScript/JavaScript programmer hat than if I’m thinking in C#. I make fewer mistakes and the code flows more naturally.
Even so, there’s a cmdlet that helps me a lot and that I think lets you write much more robust code. It’s the Set-StrictMode cmdlet. This cmdlet lets you set a series of restrictions on the code we write in PowerShell. I usually always add this line at the beginning of my scripts:
Set-StrictMode -Version 2
Version 2 determines exactly which restrictions will be applied. The options are 1, 2 or Latest. Summing up what Microsoft’s documentation explains:
1.0 – Prohibits references to uninitialized variables.
2.0 – Prohibits:
- References to uninitialized variables
- References to non-existent properties of an object.
- Calls to functions using method call syntax (using parentheses)
- The use of variables without a name (${})
Latest – Applies the strictest version available. It depends on the version of PowerShell being used, but as of today (PowerShell 5.0) the highest value is still 2.
Although the temptation might be to go for the Latest parameter, I don’t recommend it, since it could break scripts that work fine if the level of restrictions goes up in a future version of PowerShell.
With all that said, what better than an example:
function Suma($valor1, $valor2) {
return $valr1 + $valor2
}
$resultado = Suma(1, 2)
Write-Host $resultado
If I run this script with Set-StrictMode -Off the result is that nothing gets printed on screen. The reason is that the code refers to the variable $valr1 instead of $valor1. If I fix that mistake, I’ll still get an unwanted result, because “1 2” (without the quotes) will be printed on screen. This is a typical mistake when I’m wearing my C# hat: I’m calling the Suma function as if it were a method. For the script to work the way I want, it should look like this:
Set-StrictMode -Version 2
function Suma($valor1, $valor2) {
return $valor1 + $valor2
}
$resultado = Suma 1 2
Write-Host $resultado
Its similarities with TypeScript
At the beginning of the post I mentioned that over time I’ve gotten used to its closeness to TypeScript. Allowing for the differences, this could be an example based on the previous one:
Set-StrictMode -Version 2
function Suma([int]$valor1, [int]$valor2) {
return $valor1 + $valor2
}
$resultado = Suma 1 2
Write-Host $resultado
I could even twist it a bit more and get stricter:
Set-StrictMode -Version 2
function Suma {
Param(
[Parameter(Mandatory=$true)][int]$valor1,
[Parameter(Mandatory=$true)][int]$valor2
)
return $valor1 + $valor2
}
$resultado = Suma (1, 2)
Write-Host $resultado
I don’t usually go that far, since I think it makes the code too hard to read and, in most cases, I don’t need that many restrictions in the code.
Besides using Set-StrictMode, I apply TDD to develop my scripts, something that also helps a lot, especially once you start handling a lot of code. But I’ll explain that in another post.