Script to balance AD group membership.

Copper Contributor

The Security team is using Windows Event Forwarding (WEF) to collect logs from Windows workstations.  Using Windows Event Collectors (WEC) pointed to AD groups or computers objects.  But there is a maximum number of computers that each WEC can handle.  So computers have been manually divided between several AD groups.


This is a huge maintenance headache for both the help desk who adds them initially, and the security team that is ultimately responsible for it.  Especially during the constant workstation replacement projects.


They have requested a script that they can run (Probably nightly with Task Scheduler) to manage this, but I've been having a hard time finding the logic required to pull it off.  Basically it needs to take an inventory of several groups, and then distribute the members across those groups evenly (as much as possible).


The most relevant script sample I could find was of all things ,this script that Google "AI search" spit out. It was a complete mess of context errors but it gave me somewhere to start. It now works up to the point of the "$MembersToAdd" line. Meaning it appears to hash the members of the groups, remove the right amount from the larger groups, but then it "Cannot validate argument on parameter 'Members'. The argument is null or empty." when trying to add the excessive computers to the other groups.


Anyone tried anything like this before, or have an idea of what I can do to fix the end of this script?









# Import the Active Directory module
Import-Module ActiveDirectory

# Get all of the AD groups
$groups = Get-ADGroup -Filter { Name -like "TEST-ADGroupMembershipBalance*" } -Properties *

# Create a hashtable to store the group membership counts
$groupMembershipCounts = @{}

# Iterate through each group and get the membership count
foreach ($group in $groups) {
    $groupMembershipCounts[$group.Name] = $group.Members.Count

# Get the average group membership count
$averageGroupMembershipCount = $groupMembershipCounts.Values | Measure-Object -Average | Select-Object -ExpandProperty Average

# Iterate through each group and add or remove members to balance the group membership counts
foreach ($group in $groups) {
    Write-Host $group $group.Members.Count
    if ($groupMembershipCounts[$group.Name] -gt $averageGroupMembershipCount) {
        # Remove members from the group
        $membersToRemove = $group.Members | Sort-Object -Descending | Select-Object -First ($groupMembershipCounts[$group.Name] - $averageGroupMembershipCount)
        Remove-ADGroupMember -Identity $group -Members $membersToRemove
    } elseif ($groupMembershipCounts[$group.Name] -lt $averageGroupMembershipCount) {
        # Add members to the group
        $membersToAdd = Get-ADComputer -Filter * -SearchBase $group.DistinguishedName | Sort-Object {Get-Random} | Select-Object -First ($averageGroupMembershipCount - $groupMembershipCounts[$group.Name])
        Add-ADGroupMember -Identity $group -Members $membersToAdd









0 Replies