We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now

x

Check if a GPO is applied to all computers.

Can
Can asked
on
Medium Priority
48 Views
Last Modified: 2020-05-25
Hi All,

I want to check if a specific GPO is applied to all servers in my environment. Is there a way to automate this with powershell?

For example:

Import all servers from CSV then check if TESTGPO is applied?

Thanks in advance.
Comment
Watch Question

David Johnson, CDSimple Geek from the '70s
CERTIFIED EXPERT
Distinguished Expert 2019

Commented:
what does the gpo do? if it modifies a registry value then query the registry value.
Philip ElderTechnical Architect - HA/Compute/Storage
CERTIFIED EXPERT

Commented:
Click on Start and type: CMD
Right click and Run as Admin.
CD \Temp (create if not there)
GPResult /H MyGPResults.HTML

Open the file in IE or Edge.

Applied and Denied GPOs will be listed.

EDIT: Note, this will tell you exactly what GPO is applying where.
CanSystem Administrator

Author

Commented:
Thank you for your reply's
@David: The GPO has around 500+ policy's. Contains hardening policy's
@Philip: I have around 700 servers in my environment. I cant do this server by server. That why i am looking for a powershell script to automate this. 
CERTIFIED EXPERT

Commented:
Something like this?
$scangpo = "this is the name of the gpo to scan for"
$ComputerList  = Get-Content ".\computerlist.txt"
foreach ($Computer in $ComputerList) {
   Get-GPResultantSetOpPolicy -ReportType XML -Computer $Computer -Path ".\$($Computer).xml"
   $temp = Get-Content ".\$($Computer).xml"
   $rsop = [xml] $temp
   # filter applied GPOs
   $appliedgpos = $rsop.Rsop.Computerresults.GPO | Where {($_.Enabled -eq $true) -and ($_.Isvalid -eq $true) -and ($_.FilterAllowed -eq $true) -and ($_.AccessDenied -eq $false) -and ($_.Link.Enabled -eq $true)}
# check if GPO name is found
  if($appliedgpos.Name -eq $scangpo) {
    Write-Host "$($Computer): GPO detected"
  } else {
    Write-Host "$($Computer): GPO not detected"
  }
}

Open in new window


Wasn't able to really test it ..
David Johnson, CDSimple Geek from the '70s
CERTIFIED EXPERT
Distinguished Expert 2019

Commented:
pray tell where do we get the module that contains  Get-GPResultantSetOpPolicy
CERTIFIED EXPERT

Commented:
Typo
get-gpresultantsetofpolicy
CanSystem Administrator

Author

Commented:
Thank you Michael Pfister. This script seems usefull. yet im getting the following error on a lot of servers:
The Resultant Set of Policy (RSoP) report cannot be generated for user Domain\user on the Servername computer because there is no RSoP logging data  for that user on that
computer.

Which seems logical. Is there a way just to create rsop for computer policy's and not for user policy's? I havent logged in on maybe 100+ computers. 
CERTIFIED EXPERT

Commented:
I wonder, because the doc's saying it won't report user policy if you don't provide a user name with param -user

https://docs.microsoft.com/en-us/powershell/module/grouppolicy/get-gpresultantsetofpolicy?view=win10-ps

But I'v just tested and yes, it errors in case you've never logged on... very useful
CERTIFIED EXPERT

Commented:
Using the GPMgmt object looks better:
adapted from https://techcommunity.microsoft.com/t5/core-infrastructure-and-security/exporting-resultant-set-of-policy-rsop-data-using-powershell/ba-p/1217934
$scangpo = "this is the name of the gpo to scan for"

$gpmObject = New-Object –ComObject GPMgmt.GPM
$gpmConstants = $gpmObject.GetConstants()
$rsopObject = $gpmObject.GetRSOP($gpmConstants.RSOPModeLogging,$null,0)

$ComputerList  = Get-Content ".\computerlist.txt"
foreach ($Computer in $ComputerList) {
   $rsopObject.LoggingComputer = $Computer
   $rsopObject.LoggingFlags = 131072 # Only computer; no user
   $rsopObject.CreateQueryResults()       
   $rsopReport = $rsopObject.GenerateReportToFile($gpmConstants.ReportXML , "$($env:temp)\$($Computer).xml")
   $rsopObject.ReleaseQueryResults()

   $temp = Get-Content "$($env:temp)\$($Computer).xml"

   $rsop = [xml] $temp
   # filter applied GPOs
   $appliedgpos = $rsop.Rsop.Computerresults.GPO | Where {($_.Enabled -eq $true) -and ($_.Isvalid -eq $true) -and ($_.FilterAllowed -eq $true) -and ($_.AccessDenied -eq $false) -and ($_.Link.Enabled -eq $true)}
# check if GPO name is found
  if($appliedgpos.Name -eq $scangpo) {
    Write-Host "$($Computer): GPO detected"
  } else {
    Write-Host "$($Computer): GPO not detected"
  }
  remove-item "$($env:temp)\$($Computer).xml"
}

Open in new window

CanSystem Administrator

Author

Commented:
Thanks Michael Pfister, this looks way better! Im now stuck with 2 things:

1. I have 6 levels of policy's. I can now search for just one GPO. Is it possible to search for a GPO containing a name?
Example: search for "Server hardening " instead of "server hardening policy lvl1"? I tried this:
$scangpo = "*Server hardening*"
but that doesnt seem to work.

2. Some servers are offline, therefor powershell gives the following RPC errors. Is there a way to filter out offline computers? 
The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At line:11 char:4
+    $rsopObject.CreateQueryResults()
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException
 
Value does not fall within the expected range.
At line:12 char:93
+ ... portToFile($gpmConstants.ReportXML , "$($env:temp)\$($Computer).xml")
+                                                          ~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException
 
Get-Content : Cannot find path 'C:\Users\ADMIN~1.PHA\AppData\Local\Temp\3\SERVER.xml' because it does not exist.
At line:15 char:12
+    $temp = Get-Content "$($env:temp)\$($Computer).xml"
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\ADMIN...SERVER.xml:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
 
SERVER: GPO not detected
remove-item : Cannot find path 'C:\Users\ADMIN~1.PHA\AppData\Local\Temp\3\SERVER.xml' because it does not exist.
At line:26 char:3
+   remove-item "$($env:temp)\$($Computer).xml"
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\ADMIN...SERVER.xml:String) [Remove-Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand


CERTIFIED EXPERT

Commented:
Can you run

gpresult /x test.xml /Scope Computer /S Remote-SERVER 

Open in new window


?
CanSystem Administrator

Author

Commented:
Yes i can run this. But a lot of servers (around 30) are shutdown. So the RPC errors are legit. I would like to filter out offline computers. 
CERTIFIED EXPERT

Commented:
Replace
if($appliedgpos.Name -eq $scangpo)

with
$appliedgpos.Name -like $scangpo)

and you can use wildcards in $scangpo
CERTIFIED EXPERT
Commented:
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview
CanSystem Administrator

Author

Commented:
Thank you very much Michael!
CERTIFIED EXPERT

Commented:
Glad it works
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.