Automatically Capture Hard Blocker

This was one of Keith S. Garner’s (@keithga1) gifts to me before he parted ways on his new adventure.  I asked him for a script to automatically pull the Hard Blocker from the compatdata XML file created during the Windows 10 compatibility scan.  After I gave him my request, he hit me up on skype about 2 hours later and said he didn’t write a script, he wrote me a 1 liner.  Keith knows how much I like 1 liners.  Why?  Task Sequences!  If I don’t have to have content to accomplish a step, all the better!  I’ve been known to build scripts on the fly using echo >> script.bat then running the script.bat file just so I don’t have to have content.

So what’s this magic 1 line of code?  I’m getting to that.

I’ve modified it slightly, one example writes it directly to the Registry, and one that writes it to a TS Variable, and you can then do what you want with it.  I’ve added that TS Variable to be written to WMI & the Registry in my modified “SetOSDInfo” Script that I recently blogged.  I’ve updated that script as well to include this.

Registry Key:  (modify the Registry Path for your own needs)

powershell.exe -command "get-childitem 'C:\$WINDOWS.~BT\Sources\Panther\compat*.xml' | Select-object -last 1 | ? { [datetime]::ParseExact($_.Name.SubString(11,19),'yyyy_MM_dd_HH_mm_ss',$null) -gt [datetime]::now.AddDays(-1) } | % { (type $_.FUllName) -as [xml] } | % CompatReport | % Programs | % Program | ? { $_.CompatibilityInfo.BlockingType -eq 'Hard' } | % name | %{ Set-itemproperty 'HKLM:\SOFTWARE\WaaS\%SMSTS_BUILD%' 'CompatScanHardBlock' $_ }"


OSD Variable

powershell.exe -command "get-childitem 'C:\$WINDOWS.~BT\Sources\Panther\compat*.xml' | Select-object -last 1 | ? { [datetime]::ParseExact($_.Name.SubString(11,19),'yyyy_MM_dd_HH_mm_ss',$null) -gt [datetime]::now.AddDays(-1) } | % { (type $_.FUllName) -as [xml] } | % CompatReport | % Programs | % Program | ? { $_.CompatibilityInfo.BlockingType -eq 'Hard' } | % name | %{$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment; $tsenv.Value('SMSTS_HardBlocker') = $_ }"


Have the  Step set to run if TS Variable _SMSTSOSUpgradeActionReturnCode = 3247440392

Here is what my registry looks like after running the CompatScan TS with both Examples.

From a Dump of the TS Variables (using @CCMExec’s Safe Dump)

At this point, you’d then collect it with your hardware inventory and add it to your reports.

10 thoughts on “Automatically Capture Hard Blocker”

  1. Gary,
    I wanted to test new functionality but the script in the zipped file “” is dated 6/5/2018.
    And I do not see anything new or related to ‘Hard Blocker ‘ in that script.
    I am using from link for donwloads?

      • Where in the script does it pick up the registry or WMI ? I think he is saying that he has updated teh script. But i am looking and cant find anything in the script related to ‘Hard Blocker’

  2. Gary,

    One thing to consider, I was looking at the SetOSDInfo.ps1 code and CS_HardBlocker is set is error code C1900208 is returned. And this would continue as you cleared each hardblocker and if additional blockers are detected. However once you have cleared all the blockers there needs to be a line in the code that clears the record on CS_HardBlocker to be NA.

    My solution was to modify the following line:

    if ($hexreturncode -eq “C1900208”) {New-Variable -Name “$($AttributePrefix)CS_HardBlocker” -Value $tsenv.Value(“SMSTS_HardBlocker”)}

    To this:

    if ($hexreturncode -eq “C1900208”)
    New-Variable -Name “$($AttributePrefix)CS_HardBlocker” -Value $tsenv.Value(“SMSTS_HardBlocker”)
    New-Variable -Name “$($AttributePrefix)CS_HardBlocker” -Value “NA”

  3. Regarding the 1-liner for CompatScanHardBlock, the current iteration doesn’t appear to take into account multiple blockers on a device. If multiple hard blocks are found the query only writes the first 1 in the list. Perhaps a join to add all apps to the reg value?

  4. Yes, a Join would be good like suches (make semicolon seperated):
    powershell.exe -command “(get-childitem ‘C:\$WINDOWS.~BT\Sources\Panther\compat*.xml’ | Select-object -last 1 | ? { [datetime]::ParseExact($_.Name.SubString(11,19),’yyyy_MM_dd_HH_mm_ss’,$null) -gt [datetime]::now.AddDays(-1) } | % { (type $_.FUllName) -as [xml] } | % CompatReport | % Programs | % Program | ? { $_.CompatibilityInfo.BlockingType -eq ‘Hard’ } | % name) -Join ‘;’ | %{ Set-itemproperty ‘HKLM:\SOFTWARE\WaaS\%SMSTS_BUILD%’ ‘CompatScanHardBlock’ $_ }”

    • I haven’t used it in about 6 months, but when I did, I wasn’t overly impressed. The reason I have the method I do, is so that I can grab the hardblocker information while running a Task Sequence, then pull it up during hardware inventory, so it shows up in a report, vs having to use a tool to point at the panther folder on individual bases. There is probably a time and place for the tool, and should be something onsite techs use during troubleshooting if in front of the machine, but my goal was for high level reporting against a large target pool. HOWEVER, I’m hopeful this tool will continue to improve and make it easier to find other issues that happened during upgrade, typically issues in phase 2 and 3 of the upgrade, which are typically harder to troubleshoot. Eventually if this tool gets better, we’d automate it to run during an IPU Rollback, and dump the results to a share, or parse the log for useful info, and pull that up via inventory for a report as well.


Leave a Comment

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