none
List all GPOs applied to every user in the AD

    Question

  • Hi,

    I would like to generate a report with the GPOs applied to every user and every computer in the AD. The output will be like:

    users_gpo.csv:

    user1;gpo1,gpo2;gpo3

    computers_gpo.csv:

    computer1;gpo4,gpo5,gpo6

    How I can do it using Powershell or some automatic tool?.

    I tried it with gpresult but it only works if the user has a profile on the target system.

    Thanks!

    Monday, April 20, 2015 10:45 AM

Answers

  • > I tried it with gpresult but it only works if the user has a profile on
    > the target system.
     
    Obviously yes :)
     
    For your purpose, it might be most efficient to query WMI directly.
    Using a script, you can enumerate \\root\rsop\computer and
    \\root\rsop\user\<user-sid>, both have a class RSOP_GPO which contains a
    list of all applied GPOs. The property guidName contains the GPO GUID
    wich in turn can be resolved through AD search.
     

    Greetings/Grüße, Martin

    Mal ein gutes Buch über GPOs lesen?
    Good or bad GPOs? - my blog…
    And if IT bothers me - coke bottle design refreshment (-:
    Monday, April 20, 2015 11:39 AM
  • > I can get all the computers, and get de user profiles and then run the
    > query, but it is slow. *Do you know another way?.*
     
    Do not query AD for users, but query WMI \root\rsop\user for the
    namespaces it contains...
     
    > $users = Get-ADUser -Filter * | Select 'Name', 'SID'
     > $namespaceBase = "root\rsop\user\"
     
    $users = get-wmiobject -namespace $namespacebase -class "__Namespace" |
    select "Name"
     
    > foreach ($user in $users){
           $namespace = $namespaceBase + $user
     
    If required, resolve the SID through the RSOP_Session.targetName
    property in the RSOP namespace :) This class also holds Security Groups,
    Site, Distinguished Name and RSOP creationTime:
     
    __NAMESPACE      :
    ROOT\rsop\user\S_1_5_21_4063112376_1576679057_3622664657_1128
    __PATH           :
    \\DC2\ROOT\rsop\user\S_1_5_21_4063112376_1576679057_3622664657_1128:RSOP_Session.id="Session1"
    creationTime     : 20150209160440.000000+000
    flags            : 0
    id               : Session1
    SecurityGroups   : {S-1-5-21-4063112376-1576679057-3622664657-513,
    S-1-1-0, S-1-5-32-545, S-1-5-32-555...}
    Site             : Headquarters-Site
    slowLink         : False
    SOM              : OU=Backoffice,OU=Users,OU=Corp
    Root,DC=corp,DC=contoso,DC=com
    targetName       : CORP\admin-de
    ttlMinutes       :
    version          : 2228228
    PSComputerName   : DC2
     

    Greetings/Grüße, Martin

    Mal ein gutes Buch über GPOs lesen?
    Good or bad GPOs? - my blog…
    And if IT bothers me - coke bottle design refreshment (-:
    Tuesday, April 21, 2015 11:34 AM

All replies

  • > I tried it with gpresult but it only works if the user has a profile on
    > the target system.
     
    Obviously yes :)
     
    For your purpose, it might be most efficient to query WMI directly.
    Using a script, you can enumerate \\root\rsop\computer and
    \\root\rsop\user\<user-sid>, both have a class RSOP_GPO which contains a
    list of all applied GPOs. The property guidName contains the GPO GUID
    wich in turn can be resolved through AD search.
     

    Greetings/Grüße, Martin

    Mal ein gutes Buch über GPOs lesen?
    Good or bad GPOs? - my blog…
    And if IT bothers me - coke bottle design refreshment (-:
    Monday, April 20, 2015 11:39 AM
  • With this code:

    $user = "root\rsop\user\"

    Get-ADUser -filter * -Properties 'SID' | Select-Object 'SID' | Foreach-Object {
        $sid = $_.SID -replace '-', '_'
        $namespace = $user + $sid
        write-host $namespace
        Get-WmiObject -Namespace $namespace -Class RSOP_GPO | Foreach-Object {
            Write-Host $_.id
        }
    }

    Sometimes I get this error: "Get-WmiObject : Invalid namespace".

    And this code:

    $namespace = "root\rsop\computer"
    
    Get-WmiObject -Namespace $namespace -Class RSOP_GPO | Foreach-Object {
        Write-Host $_.id
    }

    It works, but how I can check another computer?.

    Thanks!




    • Edited by n108uve Monday, April 20, 2015 1:31 PM
    Monday, April 20, 2015 1:25 PM
  • > $user = "root\rsop\user\"
     
    > Get-ADUser -filter * -Properties 'SID' | Select-Object 'SID' | Foreach-Object {
    >      $sid = $_.SID
     
    The sid is not a string, but itself an object. And this SID object has
    no property "SID" (like in your code), but a property "Value" :)
     
    > It works, but how I can check another computer?.
     
    Powershell remoting or remote WMI ("\\computername\root\rsop\..." should
    do it)
     

    Greetings/Grüße, Martin

    Mal ein gutes Buch über GPOs lesen?
    Good or bad GPOs? - my blog…
    And if IT bothers me - coke bottle design refreshment (-:
    Monday, April 20, 2015 3:41 PM
  • Finally, It works for computers:

    Write-Host "Computers" -ForegroundColor Green

    $computers = Get-ADComputer -Filter * -Properties 'Name' | Select 'Name'

    $namespace = "root\rsop\computer"
    foreach ($computer in $computers){
        Write-host $computer.Name -ForegroundColor Yellow
        
        Try {
            Get-WmiObject -Namespace $namespace -Class RSOP_GPLink -Filter "AppliedOrder <> 0"  -ComputerName $computer.Name -ErrorAction Stop | Foreach-Object {
                $GPO_FILTER = $_.GPO.ToString().Replace("RSOP_GPO.","")

                #$linkOrder = $_.linkOrder
                #$appliedOrder = $_.appliedOrder
                $Enabled = $_.Enabled
                #$noOverride = $_.noOverride
                #$SourceOU = $_.SOM
                #$somOrder = $_.somOrder
                
                if ($enabled){
                    Get-WmiObject -Namespace $namespace -Class RSOP_GPO -Filter $GPO_FILTER -ComputerName $computer.Name -ErrorAction Stop | Foreach-Object {
                        Write-host "`t" $_.Name
                    }
                }
            }
        }
        Catch [System.UnauthorizedAccessException]{
            Write-host "Unauthorized Access" -ForegroundColor Red
        }
        Catch [Exception]{
            if ($_.Exception.GetType().Name -eq "COMException") {
                Write-host "`tServer unavailable" -ForegroundColor Red
            }
        }
        
        Write-host ""
    }

    But It doesn't work for users:

    Write-Host "Users" -ForegroundColor Green

    $users = Get-ADUser -Filter * -Properties 'Name' | Select 'Name', 'SID'

    $namespaceBase = "root\rsop\user\"
    foreach ($user in $users){
        Write-host $user.Name -ForegroundColor Yellow
        $namespace = $namespaceBase + $user.SID -replace '-', '_'
        Write-host $namespace -ForegroundColor Gray

        Try {
            Get-WmiObject -Namespace $namespace -Class RSOP_GPLink -Filter "AppliedOrder <> 0" -ErrorAction Stop | Foreach-Object {
                $GPO_FILTER = $_.GPO.ToString().Replace("RSOP_GPO.","")
                Write-host "`t" $GPO_FILTER

                #$linkOrder = $_.linkOrder
                #$appliedOrder = $_.appliedOrder
                $Enabled = $_.Enabled
                #$noOverride = $_.noOverride
                #$SourceOU = $_.SOM
                #$somOrder = $_.somOrder
                
                if ($enabled){
                Get-WmiObject -Namespace $namespace -Class RSOP_GPO -Filter $GPO_FILTER -ErrorAction Stop | Foreach-Object {
                        Write-host "`t" $_.Name
                    }
                }
                
            }
        }
        Catch [System.UnauthorizedAccessException]{
            Write-host "Unauthorized Access" -ForegroundColor Red
        }
        Catch {
            Write-Host "`t$_" -ForegroundColor Red
        }
        
        Write-host ""
    }

    It is working for some user but not for all, part of the output is:

    test test. test
    root\rsop\user\S_1_5_21..._1231
             LocalGPO
             Default Domain Policy
    
    gpoguy gpoguy
    root\rsop\user\S_1_5_21_..._1232
            Invalid namespace

    Why I get "Invalid namespace"?

    Thanks Martin!


    • Edited by n108uve Tuesday, April 21, 2015 11:00 AM new code
    Tuesday, April 21, 2015 9:21 AM
  • >      $namespace = $namespaceBase + $user.SID -replace '-', '_'
     
    I'd suggest using $user.sid.value - just to be on the safe side :)
     
    > root\rsop\user\S_1_5_21_..._1232
    >          Invalid namespace
     
    Has this user ever logged on to the computer? If not, then this
    namespace will not be available, so it is safe to ignore this error.
     

    Greetings/Grüße, Martin

    Mal ein gutes Buch über GPOs lesen?
    Good or bad GPOs? - my blog…
    And if IT bothers me - coke bottle design refreshment (-:
    Tuesday, April 21, 2015 11:02 AM
  • The value is OK, the problem is the user never logged on to the computer.

    So what I can do?. I want the list of GPOs applied to every user, but I don't now but it is the computer of each user.

    I can get all the computers, and get de user profiles and then run the query, but it is slow. Do you know another way?.

    I updated the code to get only de applied and enabled GPOs:

    Write-Host "Computers" -ForegroundColor Green
    
    $computers = Get-ADComputer -Filter * | Select 'Name'
    
    $namespace = "root\rsop\computer"
    
    foreach ($computer in $computers){
        Write-host $computer.Name -ForegroundColor Yellow
        
        Try {
            Get-WmiObject -Namespace $namespace -Class RSOP_GPLink -Filter "AppliedOrder <> 0"  -ComputerName $computer.Name -ErrorAction Stop |Foreach-Object {
                $GPO_FILTER = $_.GPO.ToString().Replace("RSOP_GPO.","")
    
                #$linkOrder = $_.linkOrder 
                $appliedOrder = $_.appliedOrder 
                $Enabled = $_.Enabled 
                #$noOverride = $_.noOverride 
                #$SourceOU = $_.SOM 
                #$somOrder = $_.somOrder
                
                if ($enabled){
                    Get-WmiObject -Namespace $namespace -Class RSOP_GPO -Filter $GPO_FILTER -ComputerName $computer.Name -ErrorAction Stop | Foreach-Object { 
                        Write-Host ("`t{0}: {1}" -f $_.Name , $appliedOrder)
                    }
                }
            }
        }
        Catch [System.UnauthorizedAccessException]{
            Write-host "Unauthorized Access" -ForegroundColor Red
        }
        Catch [Exception]{
            if ($_.Exception.GetType().Name -eq "COMException") {
                Write-host "`tServer unavailable" -ForegroundColor Red
            }
        }
        
        Write-host ""
    }
    
    Write-Host "Users" -ForegroundColor Green
    
    $users = Get-ADUser -Filter * | Select 'Name', 'SID'
    
    $namespaceBase = "root\rsop\user\"
    
    foreach ($user in $users){
        Write-host $user.Name -ForegroundColor Yellow
        $namespace = $namespaceBase + $user.SID -replace '-', '_'
        Write-host $namespace -ForegroundColor Gray
    
        Try {
            Get-WmiObject -Namespace $namespace -Class RSOP_GPLink -Filter "AppliedOrder <> 0" -ErrorAction Stop | Foreach-Object {
                $GPO_FILTER = $_.GPO.ToString().Replace("RSOP_GPO.","")
    
                #$linkOrder = $_.linkOrder 
                $appliedOrder = $_.appliedOrder 
                $Enabled = $_.Enabled 
                #$noOverride = $_.noOverride 
                #$SourceOU = $_.SOM 
                #$somOrder = $_.somOrder
                
                if ($enabled){
                Get-WmiObject -Namespace $namespace -Class RSOP_GPO -Filter $GPO_FILTER -ErrorAction Stop | Foreach-Object { 
                        Write-Host ("`t{0}: {1}" -f $_.Name , $appliedOrder)
                    }
                }
                
            }
        }
        Catch [System.UnauthorizedAccessException]{
            Write-host "Unauthorized Access" -ForegroundColor Red
        }
        Catch {
            Write-Host "`t$_" -ForegroundColor Red
        }
        
        Write-host ""
    }
    

    Thanks!

    Tuesday, April 21, 2015 11:16 AM
  • > I can get all the computers, and get de user profiles and then run the
    > query, but it is slow. *Do you know another way?.*
     
    Do not query AD for users, but query WMI \root\rsop\user for the
    namespaces it contains...
     
    > $users = Get-ADUser -Filter * | Select 'Name', 'SID'
     > $namespaceBase = "root\rsop\user\"
     
    $users = get-wmiobject -namespace $namespacebase -class "__Namespace" |
    select "Name"
     
    > foreach ($user in $users){
           $namespace = $namespaceBase + $user
     
    If required, resolve the SID through the RSOP_Session.targetName
    property in the RSOP namespace :) This class also holds Security Groups,
    Site, Distinguished Name and RSOP creationTime:
     
    __NAMESPACE      :
    ROOT\rsop\user\S_1_5_21_4063112376_1576679057_3622664657_1128
    __PATH           :
    \\DC2\ROOT\rsop\user\S_1_5_21_4063112376_1576679057_3622664657_1128:RSOP_Session.id="Session1"
    creationTime     : 20150209160440.000000+000
    flags            : 0
    id               : Session1
    SecurityGroups   : {S-1-5-21-4063112376-1576679057-3622664657-513,
    S-1-1-0, S-1-5-32-545, S-1-5-32-555...}
    Site             : Headquarters-Site
    slowLink         : False
    SOM              : OU=Backoffice,OU=Users,OU=Corp
    Root,DC=corp,DC=contoso,DC=com
    targetName       : CORP\admin-de
    ttlMinutes       :
    version          : 2228228
    PSComputerName   : DC2
     

    Greetings/Grüße, Martin

    Mal ein gutes Buch über GPOs lesen?
    Good or bad GPOs? - my blog…
    And if IT bothers me - coke bottle design refreshment (-:
    Tuesday, April 21, 2015 11:34 AM
  • Perfect, I know how to do it!. I'm new in PowerShell and in windows environment.

    This script has an incovenience: the computers must to be on. So, there is another way, just asking the AD?.

    Thanks a lot!


    • Edited by n108uve Tuesday, April 21, 2015 3:50 PM
    Tuesday, April 21, 2015 11:45 AM
  • > This script has a incovenience: the computers must to be on. So, there
    > is another way, just asking the AD?.
     
    If you want a list of applied GPOs, you have to query the computer.
    There's no information in AD about that...
     

    Greetings/Grüße, Martin

    Mal ein gutes Buch über GPOs lesen?
    Good or bad GPOs? - my blog…
    And if IT bothers me - coke bottle design refreshment (-:
    Tuesday, April 21, 2015 1:15 PM
  • I was thinking "query" the Group Policy Managment Console... But it is hard and you don't know if a gpo is deployed, right?.

    Thanks, I learnt a lot.

    Tuesday, April 21, 2015 3:55 PM
  • > I was thinking "query" the Group Policy Managment Console... But it is
    > hard and you don't know if a gpo is deployed, right?.
     
    GPMC can only do "modeling" - "what if"... If you want to know, you have
    to look at the client, yes.
     

    Greetings/Grüße, Martin

    Mal ein gutes Buch über GPOs lesen?
    Good or bad GPOs? - my blog…
    And if IT bothers me - coke bottle design refreshment (-:
    Wednesday, April 22, 2015 3:29 PM