Find Windows 10 Upgrade Blockers with PowerShell

This morning I saw a cool post from Gary Blok about automatically capturing hard blockers in a Windows 10 In-Place Upgrade task sequence. It inspired me to look a bit further at that, and I came up with the following PowerShell code which will search all the compatibility xml files created by Windows 10 setup and look for any hard blockers. These will then be reported either in the console, or you can write them to file where you can copy them to a central location together with your SetupDiag files, or you could stamp the info to the registry or a task sequence variable as Gary describes in his blog post. You could also simply run the script against an online remote computer using Invoke-Command.

The script is not the one-liner that Gary likes, so to use in a task sequence you’ll need to wrap it in a package and call it.

# Searches the Windows 10 Setup Compatibility logs for upgrade hard blockers
# Find all the compatibility xml files
$SearchLocation = 'C:\$WINDOWS.~BT\Sources\Panther'
$CompatibilityXMLs = Get-childitem "$SearchLocation\compat*.xml" | Sort LastWriteTime Descending
# Create an array to hold the results
$Blockers = @()
# Search each file for any hard blockers
Foreach ($item in $CompatibilityXMLs)
$xml = [xml]::new()
$HardBlocks = $xml.CompatReport.Hardware.HardwareItem | Where {$_.InnerXml -match 'BlockingType="Hard"'}
Foreach ($HardBlock in $HardBlocks)
$FileAge = (Get-Date).ToUniversalTime() $item.LastWriteTimeUTC
$Blockers += [pscustomobject]@{
ComputerName = $env:COMPUTERNAME
FileName = $item.Name
LastWriteTimeUTC = $item.LastWriteTimeUTC
FileAge = "$($Fileage.Days) days $($Fileage.hours) hours $($fileage.minutes) minutes"
BlockingType = $HardBlock.CompatibilityInfo.BlockingType
Title = $HardBlock.CompatibilityInfo.Title
Message = $HardBlock.CompatibilityInfo.Message
# Report results
If ($Blockers)
# Export to file
#$Blockers | export-csv -Path "$env:SystemDrive\Windows\CCM\Logs\W10UpgradeHardBlockers.csv" -NoTypeInformation -UseCulture -Force
Write-host "No hard blockers found"

The console output looks like this:


You should remove the FileAge property if using it in a task sequence as that’s a real-time value and is a quick indicator of when the blocker was reported.

If you use my solution here for improving the user experience in an IPU, you could also report this info to the end user by adding a script using my New-WPFMessageBox function, something like this…

$Stack = New-Object System.Windows.Controls.StackPanel
$Stack.Orientation = "Vertical"

$TextBox = New-Object System.Windows.Controls.TextBox
$TextBox.BorderThickness = 0
$TextBox.Margin = 5
$TextBox.FontSize = 14
$TextBox.FontWeight = "Bold"
$TextBox.Text = "The following hard blocks were found that prevent Windows 10 from upgrading:"


Foreach ($Blocker in $Blockers)
    $TextBox = New-Object System.Windows.Controls.TextBox
    $TextBox.BorderThickness = 0
    $TextBox.Margin = 5
    $TextBox.FontSize = 14
    $TextBox.Foreground = "Blue"
    $TextBox.Text = "$($Blocker.Title): $($Blocker.Message)"

$TextBox = New-Object System.Windows.Controls.TextBox
$TextBox.BorderThickness = 0
$TextBox.Margin = 5
$TextBox.FontSize = 14
$TextBox.Text = "Please contact the Helpdesk for assistance with this issue."


New-WPFMessageBox -Title "Windows 10 Upgrade Hard Block" -Content $Stack -TitleBackground Red -TitleTextForeground White -TitleFontSize 18

…which creates a message box like this:


Thanks to Gary and Keith Garner for the inspiration here!

3 thoughts on “Find Windows 10 Upgrade Blockers with PowerShell

  1. Trevor, have you used this in an IPU? I’m trying to implement it but I’m not getting the message box to show up when called through Invoke-PSScriptAsUser.ps1. But if I run in by itself it works with no problem (have a task sequence that’s using ServiceUI to call Powershell ISE so that I can debug).

    I made a few changes to try to debug and made just a message like you use for Show-CompatScanFailNotification.ps1 and it does show when called via Invoke-PSScriptAsUser.ps1

    So this:
    Doesn’t display when called through Invoke-PSScriptAsUser.ps1:
    New-WPFMessageBox -Title “Windows 10 Upgrade Hard Block” -Content $Stack -TitleBackground Red -TitleTextForeground White -TitleFontSize 18

    Does display when called through Invoke-PSScriptAsUser.ps1
    New-WPFMessageBox -Content $Message -ContentTextForeground Black -ContentFontWeight DemiBold -ContentFontSize 14 -Title “Windows 10 Upgrade Hard Block” -TitleFontSize 24 -TitleBackground Red -TitleTextForeground White -Sound ‘Windows Exclamation’

    Any ideas?

    1. Hi Mike, try adding this line at the beginning of the script:
      Add-Type -AssemblyName PresentationFramework,PresentationCore,WindowsBase
      When running WPF from a PS console you must do this first – it isn’t necessary in the ISE.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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