How to search GPO .xml file for drive node properties assoc. with group name?

The company I’m working for has a GPO which maps drives for users who are members of certain groups to letters and paths. We’re converting these GPOs to a new system which dynamically maps users using a logon script which looks for users in groups with a standard naming convention and in a certain OU and maps them to the path in the group description field. The migration process sometimes has errors, and I’d like to write a script to double check the process used by another group. I saw a posting by Tobias Weltner which looked like it would be a good start:

$Xml.Machines.Machine | Where-Object { $_.Name -eq 'Server0009' } | Select-Object -Property IP, {$_.Information.info1}

What I’m trying to do is look in every

$GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive node and pull every

$GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.properties.path
$GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.properties.letter
$GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.filters.filtergroup.name

where the $GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.filters.filtergroup.name -matches a group name entered in read-host or a gui menu.

Everything I’ve tried results in ALL of the paths, letters, or group names being returned, not just the ones associated with the group name entered.

Examples:

$GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive | ? {$GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.filters.filtergroup.name -match "EU_Country_drivemap_GPO"} | select ($GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.properties).path

and

$GPO_report_drives = $GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive
foreach ($GPO_report_drive in $GPO_report_drives)
{
if ($GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.filters.filtergroup.name -match "EU_Country_drivemap_GPO")
{
$GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive.filters.filtergroup.name
$GPO_report_drive.properties.path
$GPO_report_drive.properties.letter
}
}

Below is an example of one drive node:

q1:Drive clsid="{935D1B74-9CB8-4e3c-9914-7DD559B7A417}" name=“P:” status=“P:” image=“2” changed=“2011-06-21 15:32:03” uid="{3BCD4228-1598-45BE-A994-DF073740B745}" userContext=“1” bypassErrors=“1”>
<q1:GPOSettingOrder>8</q1:GPOSettingOrder>
<q1:Properties action=“U” thisDrive=“NOCHANGE” allDrives=“NOCHANGE” userName="" path="\servername\Public" label=“Country PUBLIC” persistent=“1” useLetter=“1” letter=“P” />
<q1:Filters>
<q1:FilterGroup bool=“AND” not=“0” name=“Domain\EU_Country_drivemap_GPO” sid=“S-1-5-21-1417001333-790525478-839522115-749829” userContext=“1” primaryGroup=“0” localGroup=“0” />
</q1:Filters>
</q1:Drive>

I’m trying to produce output like: Groupname Driveletter Path

for every drive letter and path for each group.

I’ll keep trying, but if someone has a solution or can point me in the right direction, I’d appreciate it.

It’s difficult to assist without seeing some example XML, which you’ll have to use GIST or it will remove all of the tags. However, the if logic is referencing an object outside of the scope of the for loop (i.e. $GPO_report), it should be looking at the context of $GPO_report_drive, something like so:

$GPO_report_drives = $GPO_report.gpo.user.extensiondata.extension.drivemapsettings.drive
foreach ($GPO_report_drive in $GPO_report_drives) {
    if ($GPO_report_drive.filters.filtergroup.name -match "EU_Country_drivemap_GPO") {
        $GPO_report_drive.filters.filtergroup.name
        $GPO_report_drive.properties.path
        $GPO_report_drive.properties.letter
    }
}

https://github.com/Tails-MATE/my-repository/blob/master/GPO_XML-example

Does this work?

Take a look at this:

https://gist.github.com/rasimmers/ee87defd8dfd80965627a8cd5bdb105c

PS C:\Users\rasim> $results

Name Groups                                                                                                         Path                                    Letter
---- ------                                                                                                         ----                                    ------
A:   {domain\domain-servers-ts, domain\domain-users-LocalComputer, domain\domain-users-Holding}                                                             A     
A:   {domain\domain-servers-ts, domain\domain-users-ComfortEnergy}                                                                                          A     
N:   {domain\domain-role-dne-technieker, domain\domain-role-domain-techniekers, domain\domain-users-Subdepartment1} \\domain.local\olddata\data1            N     
O:   {domain\domain-role-dne-technieker, domain\domain-role-domain-techniekers, domain\domain-users-Subdepartment1} \\domain.local\olddata\data2            O     
P:   {domain\domain-role-dne-technieker, domain\domain-role-domain-techniekers, domain\domain-users-Subdepartment1} \\domain.local\olddata\data1\projecten  P     
Q:   {domain\domain-role-dne-technieker, domain\domain-role-domain-techniekers, domain\domain-users-Subdepartment1} \\domain.local\olddata\data-Local       Q     
R:   {domain\domain-role-dne-technieker, domain\domain-role-domain-techniekers, domain\domain-users-Subdepartment1} \\domain.local\olddata\projecten-Local  R     
S:   domain\domain-role-dne-technieker                                                                              \\domain.local\olddata\DNE              S     
T:   domain\domain-users-Subdepartment2                                                                             \\domain.local\olddata\dne-techniekers  T     
L:   domain\domain-users-Subdepartment1                                                                             \\domain.local\data                     L     
J:   {domain\domain-app-Briljant, domain\domain-servers-ts}                                                         \\srvdomain005\data$                    J     
S:                                                                                                                  \\domain.local\domain\frigodata         S     
M:                                                                                                                  \\domain.local\userdata\home\%USERNAME% M     



PS C:\Users\rasim> $results | Where{$_.Groups -like 'domain\domain-servers-ts'}

Name Groups                                                                                     Path                 Letter
---- ------                                                                                     ----                 ------
A:   {domain\domain-servers-ts, domain\domain-users-LocalComputer, domain\domain-users-Holding}                      A     
A:   {domain\domain-servers-ts, domain\domain-users-ComfortEnergy}                                                   A     
J:   {domain\domain-app-Briljant, domain\domain-servers-ts}                                     \\srvdomain005\data$ J  

This is what I use to search my GPOs. It is simple, and you can search for any string of characters, so if you have an idea of what the GPO you’re looking for has configured, this will show you all GPOs with that bit of text. I didn’t create it myself, but I did simplify it and add some colors to the output the make it even easier.

<#
Search all the GPO objects for a bit of text from a configured option
#>
# Ask for something to query
$string = Read-Host -Prompt "What are you looking for?"

The business bits…

$DomainName = $env:USERDNSDOMAIN
write-host “Finding all the GPOs in $DomainName” -foregroundcolor Magenta
Import-Module grouppolicy
$allGposInDomain = Get-GPO -All -Domain $DomainName
Write-Host “Starting search…” -foregroundcolor Cyan
foreach ($gpo in $allGposInDomain) {
$report = Get-GPOReport -Guid $gpo.Id -ReportType Xml
if ($report -match $string) {
write-host “Match found in: $($gpo.DisplayName)” -foregroundcolor darkblue -backgroundcolor white
}
else {
Write-Host “No match in: $($gpo.DisplayName)”
}
}

Rob;

I haven’t tested the code yet, but I understand the concept. The final outcome doesn’t have to be done in one pass. The first part is to search all the drive nodes, gather ALL the combinations, into an object/format that enables easy access, then step 2 is to filter for the group name I’m looking for. Excellent. As for the pscustomobject; my background is over 25 years of Windows administration, relying on windows batch, and a few other scripting languages. My use of powershell has increased gradually during the last 3 years, with little formal training. The idea of creating a pscustomobject to gather and hold all the information didn’t occur to me. It looks so simple. I’ve gotten used to pulling pieces of information from the properties (hash tables) of powershell objects, but not creating my own…yet.

Thank you.

Now I see my logic error. I was referencing everything from the top of the file, and not just within each drive node. duh… The foreach loop would also work fine.