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.
Gary,
I wanted to test new functionality but the script in the zipped file “https://garytown.com/Downloads/WaaS-PreCacheCompatScan.zip” 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?
Thanks,
Mike,
I don’t believe Gary has updated the sequence yet but has provided you with the steps to update it yourself. After you import the task sequence go and update the SetOSDInfo.ps1 file in the WaaS_Scripts package with the information found here (https://garytown.com/collect-osd-ipu-info-with-hardware-inventory) and then add the steps listed above into your sequence.
Hope this helps.
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’
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”)
}
else
{
New-Variable -Name “$($AttributePrefix)CS_HardBlocker” -Value “NA”
}
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?
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’ $_ }”
Hey Gary,
Have you looked at the new SetupDiag tool. Wondering if this makes it easier to pull in the information rather than the powershell script.
https://docs.microsoft.com/en-us/windows/deployment/upgrade/setupdiag
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.