且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

“该行已经属于该表”当使用POWERSHELL向表中添加数据时

更新时间: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
}

相关阅读

推荐文章