PowerShell CIM CmdLets – Working with lazy properties

In my last post, I explained how to solve one of the stumbling blocks when working with the PowerShell CIM CmdLets. The second problem, which was both pretty nasty as it basically prevented me from using the CIM CmdLets properly for SCCM and pretty time consuming, as it was hard to find a solution, was working with lazy properties.

The Problem

Lazy properties are unique to SCCM. As some of the objects in SCCM can be pretty large or can consume a lot of resources, the SCCM WMI provider has an additional qualifier called “lazy”. All poperties that are marked with this qualifier won’t be returned on default. That means, if you e.g. get a list of SMS_AuthorizationList items, which is the equivalent of the “Software Update Groups” in the ConfigMgr console. the Updates property that contains a list of Updates of this Software Update Group, will be there, but it will be null. Or better, not set.

Why is this an issue?

First, you might actually need the value in your script. E.g. the above mentioned list of updates is probably one of the more important information in this object.

The bigger issue, which is actually a real big problem, arises, if you are trying to update an object. Lets assume you want to change the description of a SCCM object. So you query for this object and filter e.g. by the current name or its ID or similar. Then you update the description property and as soon as you save this object back to WMI, you have basically corrupted it, as all lazy properties have been erased! Be sure you wouldn’t be the first one that ran into this issue.

However, the object returned by Get-CimInstance has neither a __PATH property nor does it have a Get() (or equivalent) method!

The Solution

This was a really nasty problem for me, as I had started converting most of my scripts that deal with WMI related operations using the CIM CmdLets. And I was unable to find a proper solution. I wasn’t the only one as e.g Trevor Sullivan published an Introduction to the CIMCmdlets PowerShell Module on The Scripting Guys blog saying:

For example, people who are automating Microsoft System Center 2012 Configuration Manager, the lack of the __PATH property value is highly detrimental, as it does not allow them to deal with WMI classes & properties marked with the “Lazy” qualifier.

So whenever I had to deal with lazy properties in SCCM I had to fall back to the WMI CmdLets. Basically making the benefits of the CIM CmdLets useless.

At the end, the solution came again from the post CIM Cmdlets – Some Tips & Tricks from the PowerShell team. It wasn’t obvious, but “Tip #10 Making Get/Enumerate efficient” did the trick finally. They demonstrated how to refresh the data of an object, without retrieving it again:

PS:> # Get instance of a class
PS:> $p = Get-CimInstance -ClassName Win32_PerfFormattedData_PerfOS_Processor
PS:> # Perform get again by passing the instance received earlier, and get the updated properties. The value of $p remains unchanged.
PS:> $p | Get-CimInstance | select PercentProcessorTime

The solution is to update the current “limited” object that doesn’t contain any value for lazy properties, but the properties themselves, by passing it to the Get-CimInstance CmdLet and then save it back to the original (or optionally a new) object.

I hope you find this tip valuable. I was honestly struggling with this for months. So for me it definitely is, as I can now concentrate on one set of CmdLets without taking care about what type of CmdLet to use for what type of operation.