WaaS PreAssessment & PreFlight using Config Items

First off,

Why CIs?  Because they are easy to maintain, allow us to use them for both PreAssessment & PreFlight.  If you’re asking what those are, please stop and go here: https://miketerrill.net/2019/01/01/windows-as-a-service-in-the-enterprise-table-of-contents/, then read the blog post: Windows as a Service in the Enterprise Overview Part 1.

Now that you understand the process…

Here is what they look like in the console:

Examples for an Application:

Detection Method… how do we know if the software is installed?

(Get-WmiObject -Namespace 'root\cimv2\sms' -Query "SELECT ProductVersion FROM SMS_InstalledSoftware where ARPDisplayName like 'GreenShot%'").ProductVersion

Setting (Info we Pull to check if Compliant)


Code: Same as Detection (Not always, just because that’s how I write the Detection)


Compliance Rules: (Rules to compare to the data pulled back from the Setting)

Place the Version values of the “Approved” versions into the “One Of” List.

For Hardware Models that we want to flag as non-compliant…

Example: HP Models

Code: if ((Get-WmiObject win32_computersystem).Manufacturer -like "H*"){Write-Host "HP"}




Code: if ((Get-WmiObject win32_computersystem).Manufacturer -like "Dell*"){Write-Host "Dell"}

Setting: (Please note, not same Class as HP)



As for the other CIs… I’m not going to get into them here.  They are all in the download, you can import them and poke around.

So now that you’ve got your CIs, you add them all to a baseline..

You’ll add all of your CI’s to your Baseline, for Applications, for Applications (Besides the CM Client), we set it to Optional, because we only care about which version it has installed if the software is installed.  If for example, GreenShot is NOT installed on the machine, I’m not going to flag it as non-compliant.  I will only say something is non-compliant if a software IS installed, and DOES NOT match an approved version.  However, for our hardware models, those were required, because if it matched one of the settings, it would be non-compliant.

So now you have your CIs & Baseline, you’ll want to deploy that to a collection so you can start finding Non-Compliant Machines.


On your machines, this is what you want to see:

But if you have something non compliant:


At this point, you can check reports for why it’s non-compliant or you can check the local client


From the report, you can see that we have several applications that are Not Detected, which is cool, if it’s not there, then I don’t care, but look, Chrome is installed, and it is Non-Compliant, it has the wrong version installed.

Lower down in the report it gives details:

From here you can see that it is looking for Version 72, which is the version blessed for the upgrade, but it is running version 74.X, which has not been tested and blessed, so it is marked non-compliant.

This is an odd example, typically the “current version” would be less than what we’re looking for.  But it proves a point, even newer versions of a software are non-compliant, if we haven’t tested that version, then I don’t want to approve it willy nilly.

Auto Remediation of the Non-Compliant software is pretty easy as well.

Based on Query, you can have Collections of non-compliant items.


The CIUnique ID is shown on the CI itself.. please remember, it changes each time you modify the CI…. so if you change the CI, you need to update the Query


The last character of the Unique ID = Version of the CI… so it changed each time you change the CI

So that’s how we have our PreAssessment Setup.  How do you use that information in a PreFlight in a Task Sequence… well, that’s a bit more tricky.

The Machine running the PreFlight is in a collection that has the Baseline Targeted to it.

That means that the Baseline is on that machine and in the WMI Policy for ConfigMgr

Guess what… it’s basically XML in WMI.. Powershell is pretty good at reading XML  So how do we leverage it?  During the Task Sequence, we run a powershell script that looks up that Baseline in WMI, reads through the XML, determines if the Baseline was Complaint or not, then either fails out or continues.

Example of what happens if it finds a non-compliant item

Code (Full code will be available in the Download of the WaaS Task Sequence.)
This snip is finding the Baseline Info for a baseline that’s name is like Pre-Assessment, then checks for the non-complaint items.  It also triggers another validation of the Baseline

The script will first check to see when the last evaluation and what the result was.  If it was less than 24 hours ago, and it was complaint, then it continues on, if the baseline was non-compliant in the last 24 hours, it will wait for the evaluation to run to see if it now compliant, then either fail or continue on. (Shown Below)

So in the TS… it’s just a run PS Step.


And there you have it… to get it… it’s part of the WaaS 1809 Download Pack.
Download Pack https://garytown.com/waas-1809-ts-collection



12 thoughts on “WaaS PreAssessment & PreFlight using Config Items”

  1. Hi, i was surprised that Chrome is able to corrupt ipu process... What is your recommendation? Delete them? We are going to migrate 6000 machinse fron 1703 to 1809. You've done great work. Thanks a lot.

    • I don't believe chrome is an issue. The Baseline I provided is an example of different applications to help provide an understanding of how it works and allows you to test the Baseline. The ones provided are not recommended for production, you'll have to determine that for your own environment. Thanks for the comment, I should have clarified that

  2. Hi Gary! This is great work! To add on to Alexandr's question about required CI's, if we just delete the CI's we don't want in our production version from the baseline, is that all that needs to be done, or do we need to modify something inside the PS1 script as well?

  3. Small one, WaaSExport-2019-08-09T15-41-31.zip CI for Symantec Endpoint Protection, small change in discovery script:

    (Get-WmiObject -Namespace 'root\cimv2\sms' -Query "SELECT ProductVersion FROM SMS_InstalledSoftware where ARPDisplayName = 'Symantec Endpoint Protection'").ProductVersion

    instead of

    Get-WmiObject -Namespace 'root\cimv2\sms' -Query "SELECT ProductVersion FROM SMS_InstalledSoftware where ARPDisplayName = 'Symantec Endpoint Protection'"

    Astonishing Job! Great pleasure to go deeper and deeper in your scripts/solutions/ideas fact you shared it for free is unprecedented these days

  4. Any reason why you cant choose "is like" and use a % for the last digits after the / for the CI's in the query so you dont have to keep updating?

    • It's an organizational decision. We test the upgrade and certify with specific versions of software.
      If someone has a different version, even newer, we won't allow the machine to upgrade because it didn't get regression testing with that version.
      There are already so many variables during an upgrade, so we remove as much risk as possible by strictly controlling important software versions during upgrade.

      It's all about risk and SLAs. If you aren't as controlled and want to assume all newer versions will not cause adverse effects, you can do wild cards.

  5. Hi Gary
    Amazing work!

    If I understand this correctly, your WMI query gets the info from a ConfigMgr data class which relies on the inventory process?
    (Get-WmiObject -Namespace 'root\cimv2\sms' -Query "SELECT ProductVersion FROM SMS_InstalledSoftware where ARPDisplayName like '7-Zip%'").ProductVersion

    I usually do this by querying the uninstall keys in registry. Feels more accurate to me and factors out the inventory schedule.
    (Get-ChildItem HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall,HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall | Get-ItemProperty | Where-Object {$_.DisplayName -like '7-Zip*'}).DisplayVersion

    Short version:
    (gci HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall,HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall | gp | ? {$_.DisplayName -like '7-Zip*'}).DisplayVersion

    Even shorter since PowerShell 3
    (gci HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall,HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall | gp | ? DisplayName -like '7-Zip*').DisplayVersion

    For all who want to stick with WMI, Get-WmiObject is deprecated, better use Get-CimInstance now. Syntax is similar.
    (Get-CimInstance -Namespace 'root\cimv2\sms' -Query "SELECT ProductVersion FROM SMS_InstalledSoftware where ARPDisplayName like '7-Zip%'").ProductVersion

    Happy scripting


Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.