How can I combine set-strictMode -version 2 in a PowerShell Script (not function) with the param statement?

Viewed 156

When I run the following script, I get a The variable '$windowHeight' cannot be retrieved because it has not been set. error message.

set-strictMode -version 2

param (
  [parameter(Mandatory=$false)] [Int32] $windowHeight,
  [parameter(Mandatory=$false)] [Int32] $windowWidth
)

echo "windowHeight: $windowHeight"
echo "windowWidth:  $windowWidth"

This error message goes away if I remove the set-strictMode statement.

Is it somehow possible to use set-strictMode -version 2 together with the param statement, without getting an error message?

2 Answers

To elaborate on Gert Jan Kraaijeveld's helpful answer:

A param(...) block must be the first statement in a script (or function) in order to work - with the following limited exceptions:

  • in v5+, using statements may precede it - see about_using.

  • comments may precede it,

    • which includes #Requires comments, which state requirements evaluated / ensured before the script runs - see about_Requires

Arguably, placing any other statements before param(...) should be caught at parse time, but as of PowerShell 7.0, the error occurs at runtime, which can result in unhelpful error messages:

Technically, what happens is that a command mistakenly placed before the param(...) block changes the latter's interpretation to considering param the name of a command (alias, function, script, or executable) - which typically doesn't exist.

Because the misplaced command happened to be a Set-StrictMode call in your case, the arguments to the command-that-isn't were evaluated first, and a reference to a non-existent $windowHeight (which then wasn't treated as a parameter variable) caused the strict-mode error you saw.

Had you placed a different command first, the misinterpretation of param as a command name would have become more obvious:

The term 'param' is not recognized as the name of a cmdlet, function, script file, or operable program. [...]

While this is better than the misleading strict-mode error, as stated, a parse-time error with a dedicated, specific error message would be much better.

The param statement should come first. So move the Set-StrictMode line a few lines down. Then it works. Make the parameters mandatory if you want them provided at all times

Related