更新时间:2023-12-01 09:21:52
You are running a ForEach and the first thing is an If clause where you define $strGroupMember, which you reference in the Else clause for the same If/Then. Here, this is simplified:
IF($Group.ObjectClass -eq "group"){
<do stuff>
$strGroupMember = get-aduser $strnestedgroup <more parameters>
$row2.stuff = $strgroupmember.stuff
}
Else{
$row2.stuff = $strgroupmember.stuff
}
But you don't define $strgroupmember in the else scriptblock at all. So it's then adding the last one from the last group, and it already has that entry, so it throws an error.
With fake data.... Group is Administrators, it contains 1 group ("Payroll" which has 1 member, "John") and 2 users ("Jim" and "Sally").
ForEach($Item in get-adgroupmember "Administrators"){
if($Item.ObjectClass -eq "group"){ #Payroll is a group, it gets processed here
ForEach($User in $Item){
$Userdata = Get-ADUser $User #Returns Jim's AD info
$Row2.name = $Userdata.name
$Row2.description = $Userdata.description
$Table2.add($Row2) #Adds John to the table
}
}
Else{ #if not a group, process root users here, should process Jim and Sally
$Row2.Name = $Userdata.name #$Userdata still contains John's info
$Row2.Description = $Userdata.Description #$Userdata still contains John's info
$Table2.add($Row2) #attempts to add John to the table again
}
Hopefully that all made sense. Or at least enough of it that you see the issue. The fix? Add one line to your Else scriptblock:
$strGroupMember = Get-aduser -Identity $Group -property description
Edit: I'd make an array, create user object and add them to the array, and then iterate through nested groups and add that group to each user object that it applies to, then push that data into a table so you'd end up with something like:
Name Description NetworkID Nested
John John Smith JSmith Payroll,HR
Mark Mark Jones MJones Not Nested
Mary Mary Anderston MAnderson HR
But that's me.
Edit2: Ok, round 2! I see changes, but there's still some issues for sure. The issue you are coming across is adding rows to the table. Ok, understandable. Here's some issues I see:
foreach($strNestedGroup in $strGroupDetails)
{
#$strNestedGroupName = $Group.name
$strGroupMember = Get-aduser -Identity $StrNestedGroup -property description
$row2.Nested = "(From NESTED GROUP: " + $strNestedGroupName
$table2.Rows.Add($row2)
}
Ok, for each item in the nested group query AD and store the results in $strGroupMember
. Then update $row2.nested
to the current group's name, and add $row2
to the table as a new row. So let's just say we enter this loop with $row2
being this:
$row2.Name = "John Smith"
$row2.Description = "Director of HR"
$row2.NetworkID = "JSmith"
$row2.Nested = "Not Nested"
Ok, it's looping through the entries that it pulled for the nested group "Power Users". We'll make this easy and assume there are not additional groups nested within this nested group, that's a whole other issue.
Item 1 on that list is Marcia Winkle, she has an AD description of "Payroll", and a user name of MWinkle. The loop found that out and assigned all her info to $strGroupMember
.
Next it updates $row2
, and replaces the Nested
value, replacing "Not Nested" with "From nested group: Power Users" (the group we are working with).
Then it adds $row2
to $table2
, creating a row:
Name Description NetworkID Nested
John Smith Director of HR JSmith From nested group: Power Users
Ok, done! Next member of the group is Ethel Jones. She too has the description of Payroll, and her user name is EJones. The loop pulled that from AD, and replaced any existing values of $strGroupMember
with them. Not that it matters, we didn't seem to ever use any of that info in the last loop anyway, but that's not the script's concern, it just powers through!
Next, we update $row2.Nested
again, changing "From nested group: Power Users" to "From nested group: Power Users" ...huh, same thing as before, but ok, you're the boss. Moving on!
Now it attempts to add another row to the table, but here's where we get an error: It's the exact same data as last time since nothing in $row2 was really changed, it's still:
Name Description NetworkID Nested
John Smith Director of HR JSmith From nested group: Power Users
You see where I'm going here? Next issue I see is that you are doing an If/Then/Else cycle here, but you are trying to add rows in the Then section, but not in the Else section. Here, take this ideology and update your code accordingly:
If (Is a Group) Then
For Each Member of the group, do this
query AD to get user details
Update the $row2 variable with the user's details and the current group
Add $row2 to the table
End For Each loop
Else (if it is NOT a group)
query AD to get the user's details
Update the $row2 variable with the user's details and the current group
Add $row2 to the table
End Else section
This should clear up your current errors. It doesn't recurse more than one level of groups, so you will miss people if there's a group within a group, within a group. As in:
Main Group
--->Nested Group
--->Another Nested Group
->Billy Mac
That will include the first nested group, and the second nested group, but unless he is represented somewhere else Billy Mac will not make it in your list.
As for my solution, I had most of this written up last night so I finished it up today. This should do what you want I think. It creates an empty array, then populates it with an object for every user found recursively. Then it cycles through all nested groups and adds that group's name to the Nested property of the object of each user in it. Then it outputs that array as a CSV file for each group processed.
import-module activedirectory
#Define a function to add a group's name to its members Nested field recursivly.
Function GetNestedMembers{
Param($Group)
ForEach($Item in (Get-ADGroupMember $Group)){
if($Item.ObjectClass -eq "group" -and $Global:SubGroups -inotcontains $Item.name){
$Global:SubGroups += $Item.name.tostring()
GetNestedMembers $Item
}else{
$AllMembers|?{$_.Name -match $Item.Name -and !($_.nested -match $group.name)}|%{$_.Nested = "$($_.Nested), $($Group.Name.tostring())"}
}
}
}
$GroupList = get-content "C:\Users\MYUSERNAME\Documents\Group Audit\audit.txt"
ForEach($Entry in $GroupList){
$SubGroups = @()
#Create an empty array
$AllMembers = @()
#Populate it with all recursive members of the group
ForEach($Person in (Get-ADGroupMember $Entry -Recursive)){
$User = Get-ADUser $Person -Property description
$AllMembers += New-Object PSObject -Property @{
Name = $Person.Name
Description = $User.Description
NetworkID = $Person.SamAccountName
Nested = $Null
}
}
$CurrentGroup = Get-ADGroupMember $Entry
#Mark root members as direct group members in the Nested field
$AllMembers|?{($CurrentGroup | ?{$_.ObjectClass -ne "group"}).name -contains $_.Name}|%{$_.Nested = "Direct Member"}
#Iterate through all nested groups
$CurrentGroup | ?{$_.ObjectClass -eq "group"} | %{GetNestedMembers $_}
#If the output path doesn't exist, make it quietly.
If(!(Test-Path "C:\Users\MYUSERNAME\Documents\Group Audit\groups\")){$null = New-Item "C:\Users\MYUSERNAME\Documents\Group Audit\groups\" -ItemType directory}
#Output to CSV
$AllMembers |%{if($_.nested){$_.nested = $_.nested.TrimStart(", ")};$_} | Select Name, Description, NetworkID, Nested | Export-csv "C:\Users\MYUSERNAME\Documents\Group Audit\groups\$Entry.csv" -NoTypeInformation
}