How to Configure Windows Server 2019 Group Policy Troubleshooting

Group Policy troubleshooting is one of the most common tasks for Windows Server administrators. GPO issues can manifest as settings not applying, inconsistent behavior between users or computers, slow logon times, or unexpected policy applications. Windows Server 2019 provides a comprehensive set of tools for diagnosing and resolving Group Policy problems. This guide covers a systematic approach to troubleshooting GPOs using built-in utilities.

Step 1 — Verify Group Policy Processing with gpresult

The gpresult command is the primary diagnostic tool for Group Policy. It shows which GPOs were applied, which were filtered, and which encountered errors. Run it locally on the affected machine as the user experiencing the issue:

gpresult /r

Generate a detailed HTML report (much more comprehensive than /r output):

gpresult /h C:GPOReport.html /f
Start-Process C:GPOReport.html

Run gpresult against a remote computer for a specific user:

gpresult /s WORKSTATION01 /u contosojsmith /r
gpresult /s WORKSTATION01 /u contosojsmith /h C:GPOReport_jsmith.html /f

Understanding gpresult Output

The gpresult output has two critical sections: Applied GPOs and Denied GPOs. Denied GPOs show why a GPO did not apply — common reasons include WMI Filter failed, Security filter, or Empty (no settings configured). Review the Applied GPOs section:

gpresult /r /scope computer
gpresult /r /scope user

If a GPO shows under “Denied GPOs” with reason “Inaccessible”, check SYSVOL replication and GPO permissions. If the reason is “Filtered out (Security)”, verify the computer or user account has “Apply Group Policy” permission on the GPO.

Forcing a Group Policy Update

Force an immediate policy refresh on the local machine:

gpupdate /force

Force a policy refresh on remote computers from the domain controller or management workstation:

Invoke-GPUpdate -Computer "WORKSTATION01" -Force
Invoke-GPUpdate -Computer "WORKSTATION01" -Force -LogOff
Invoke-GPUpdate -Computer "WORKSTATION01" -Force -Boot

Force a policy refresh on all computers in a specific OU:

$computers = Get-ADComputer -SearchBase "OU=Finance,DC=contoso,DC=local" -Filter *
$computers | ForEach-Object {
    Invoke-GPUpdate -Computer $_.Name -Force -ErrorAction SilentlyContinue
}

Reviewing the Group Policy Event Log

The Group Policy operational log contains detailed per-GPO processing events. This is the most valuable source for diagnosing why specific settings fail to apply:

Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 200 |
    Where-Object {$_.LevelDisplayName -ne "Information"} |
    Format-List TimeCreated, Id, LevelDisplayName, Message

Find errors related to a specific GPO by name:

Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" -MaxEvents 500 |
    Where-Object {$_.Message -like "*Password Policy*"} |
    Format-List TimeCreated, Id, Message

Check for GP processing time (slow logons are often caused by slow GPO processing):

Get-WinEvent -LogName "Microsoft-Windows-GroupPolicy/Operational" |
    Where-Object {$_.Id -eq 8004} |
    Select TimeCreated, @{N='Message';E={$_.Message.Substring(0,300)}} |
    Sort TimeCreated -Descending |
    Select -First 10

Diagnosing WMI Filter Issues

WMI filters are a common source of GPO application failures. Test a WMI query directly on the target computer to verify it returns the expected result:

$wmiQuery = "SELECT * FROM Win32_OperatingSystem WHERE Version LIKE '10.0%' AND ProductType = '3'"
$result = Get-WmiObject -Query $wmiQuery
if ($result) {
    Write-Output "WMI Filter PASSED - GPO would apply"
} else {
    Write-Output "WMI Filter FAILED - GPO would NOT apply"
}

Checking GPO Permissions and Links

Verify the GPO is linked to the correct OU and that the target object has the necessary permissions:

$gpo = Get-GPO -Name "Finance Password Policy"
$gpo | Format-List DisplayName, GpoStatus, CreationTime, ModificationTime

Get-GPPermission -Name "Finance Password Policy" -All |
    Select TrusteeName, TrusteeType, Permission

Verify the GPO is linked and not blocked by a parent OU:

Get-GPInheritance -Target "OU=Finance,DC=contoso,DC=local" |
    Select-Object -ExpandProperty GpoLinks |
    Format-Table DisplayName, Enabled, Enforced, Order

Get-GPInheritance -Target "OU=Finance,DC=contoso,DC=local" |
    Select BlockInheritance

Checking SYSVOL Accessibility

GPOs fail to apply if their policy files in SYSVOL are inaccessible. Check SYSVOL replication status and share availability:

$dcs = (Get-ADDomainController -Filter *).Name
foreach ($dc in $dcs) {
    $sysvol = Test-Path "\$dcSYSVOL"
    $path = "\$dcSYSVOL$env:USERDNSDOMAINPolicies"
    $accessible = Test-Path $path
    Write-Output "$dc | SYSVOL Share: $sysvol | Policies folder: $accessible"
}

dfsrdiag PollAD /verbose

Using the Policy Analyzer Tool

Microsoft Policy Analyzer is a free tool that compares GPO settings between different GPOs or against a baseline. Download it from the Microsoft Security Compliance Toolkit and use it to identify duplicate, conflicting, or redundant settings:

PolicyAnalyzer.exe
# File > Add Files to Compare > Browse to GPO backup folder
# Compare multiple GPOs to find conflicts and duplicates

Export GPO settings to XML for offline analysis:

Backup-GPO -All -Path "C:GPOBackups$(Get-Date -Format yyyyMMdd)"
Get-GPO -All | ForEach-Object {
    Get-GPOReport -Guid $_.Id -ReportType Html -Path "C:GPOReports$($_.DisplayName -replace '[\/:*?"|]','_').html"
}

Systematic Group Policy troubleshooting on Windows Server 2019 starts with gpresult to identify the applied/denied GPO set, then drills into the GP operational event log for error specifics, then checks SYSVOL accessibility, permissions, and WMI filter behavior. Keeping the GP operational log retention period set to at least 7 days provides enough history to correlate policy failures with reported user issues.