Powershell: Set-StrictMode -Version Latest

by Ryan 30. July 2013 13:13

Set-StrictMode is a wonderful Cmdlet that you should use in every script you write.  It will save you hours of debugging and frustration from things like fat-fingered variable and property names.  Here is what version 2 of Set-StrictMode does:

-- Prohibits references to uninitialized variables (including uninitialized variables in strings).
-- Prohibits references to non-existent properties of an object.
-- Prohibits function calls that use the syntax for calling methods.
-- Prohibits a variable without a name (${}).

If you apply Set-StrictMode to some of your old scripts, you'll be surprised at how many new errors it will throw at you. This is good though, because it encourages you to write safer, cleaner code with less bugs.  Number 2 on the list above was giving me fits today, however.  Let me give you an example.

$Users = Get-ADUser -Filter * -Properties *

Now let's say that I am interested in the EmployeeId attribute of the users. Even though I specified -Properties *, the user objects in the collection may or may not have a property called EmployeeId. The user object will not have an EmployeeId property that is blank or null.  If the attribute is not populated in Active Directory, the Cmdlet omits the property entirely.  So in a script without Strict Mode, I could just do

Foreach($User In $Users) { If($User.EmployeeId) { ... } }

And it would function as expected, running the code block if the user had an EmployeeId, and skip it otherwise. But with Strict Mode, you'll see a lot of this:

Property 'EmployeeId' cannot be found on this object; make sure it exists.
At line:1 char:9
+ $User. <<<< EmployeeId
    + CategoryInfo          : InvalidOperation: (.:OperatorToken) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFoundStrict

Even if I did

$Users = Get-ADUser -Filter { EmployeeId -NE $Null } -Properties *

or

$Users = Get-ADUser -Filter * -Properties * | Where-Object { $_.EmployeeId -NE $Null }

I would still get the errors when running through the Foreach loop, even though that should have given me only the users with EmployeeIDs. So I need a way to test for the existence of an object property, rather than just assuming that a null value returned when the property is referenced is good enough.

If($User -NE $Null -AND $User.PSObject.Properties.Match('EmployeeId').Count) { ... }

This works. The -AND operator in Powershell works like a "short circuit" && operator in most programming languages, meaning that if the first expression does not satisfy the requirements for entering the code block, then the second expression is not evaluated. This is perfect, because if I accidentally feed a null user object to the code above, I would have gotten the same error about the $User object not containing a PSObject property.

Alright, back to scripting!

Add comment

About Me

Name: Ryan Ries
Location: Texas, USA
Occupation: Systems Engineer 

I am a Windows engineer and Microsoft advocate, but I can run with pretty much any system that uses electricity.  I'm all about getting closer to the cutting edge of technology while using the right tool for the job.

This blog is about exploring IT and documenting the journey.


Blog Posts (or Vids) You Must Read (or See):

Pushing the Limits of Windows by Mark Russinovich
Mysteries of Windows Memory Management by Mark Russinovich
Accelerating Your IT Career by Ned Pyle
Post-Graduate AD Studies by Ned Pyle
MCM: Active Directory Series by PFE Platforms Team
Encodings And Character Sets by David C. Zentgraf
Active Directory Maximum Limits by Microsoft
How Kerberos Works in AD by Microsoft
How Active Directory Replication Topology Works by Microsoft
Hardcore Debugging by Andrew Richards
The NIST Definition of Cloud by NIST


MCITP: Enterprise Administrator

VCP5-DCV

Profile for Ryan Ries at Server Fault, Q&A for system administrators

LOPSA

GitHub: github.com/ryanries

 

I do not discuss my employers on this blog and all opinions expressed are mine and do not reflect the opinions of my employers.