Add one or more users to one or more security groups in Active Directory

I have covered this topic in a previous post, but in that occasion I only explained how to add one or more users to a single group. Sometimes you have different requirements, and it could be useful to be able to add one or more users to one or more groups with the same script. With that in mind, let’s see what we can do to achieve that with PowerShell.

The first thing we need is the input. For this case we can use Import-Csv, Import-Clixml, ConvertFrom-Json… or just create an array. For users we will use the sAMAccountName property and for groups the Name property. To keep things simple, just to show you the logic of the script, let’s use an array for both users and groups:

$users = @(
    "user1"
    "user2"
)

$groups = @(
    "group1"
    "group2"
)

Now we have to determine what we need to do with the data in $users and $groups. Since we have to add every user in $users to each group in $groups, a FOR can be handy. According to MS documentation, the following is the syntaxis of the FOR loop in PowerShell:

for (<Init>; <Condition>; <Repeat>)
{
    <Statement list>
}
  • <Condition> this placeholder represents a condition that PS will evaluate with every iteration. If it evaluates to $false, the loop will stop. Of course, we cannot use a fixed value since that deviates the whole purpose of the loop. We need a dynamical value and that is exactly the number of elements that $users contains. That said, we want the loop to run while $i is less than the number of elements in $users. That means that if $i = 3 and the number of elements in $users is equal to 3, the loop will not run because at that point we know that we have iterated through all the elements in $users. Since this could be tricky to understand, lets remembers that the index of an array starts at 0, and with that in mind the following table could be useful to understand this:
IterationValue of $iIndex of the element in $users array$i is less than the number of elements in $users
10$users[0] = “user1”$true
21$users[1] = “user2”$true
32$users[2] = “user3”$true
43$users[3] = “”$false
Running the for loop for $users
  • As you can see, we are using the value of $i to access the element with that same index value in $users. To count the amount of elements in $users we can use .Count ($users.Count).
  • <Repeat> this instruction will take <Init>, in our case $i, and will increase its value by 1 with each iteration. In the first iteration $i will have a value of 0, then 1… and so on until the <Condition> evaluates to $false. In short, we can tell PS to increase the value of $i by 1 with each iteration with “$i++” or “$i+=1”.

At this point, our loop looks like this:

for ($i = 0; $i -lt $users.Count;$i++)
{
    <Statement list>
}

Now, we already took care of $users, but now we also need to do something with the elements in $groups. For this we will be using another loop. This is commonly known as a nested loop which has an outer loop (the one for the users) and an inner loop (the one for the groups). Luckily for us, is almost the same thing as with the first loop with two small changes: $j instead of $i as a counter and our condition is going to be evaluated against the number of elements in $groups instead of $users. This second loop looks like this:

for ($j = 0; $j -lt $groups.Count;$j++)
{
    <Statement list>
}

Here we have to join the loops to form the nested loop and we also have to add a couple of variables that will help us to avoid problems. In the loop for $users (outer loop) we want to create a variable with the name of the user for that iteration. The same goes for the inner loop for $groups. As said before, $i and $j will refer to the index of the element in the array:

for ($i = 0; $i -lt $users.Count;$i++)
{
    $userLooping = $users[$i]
    for ($j = 0; $j -lt $groups.Count;$j++)
    {
        $groupLooping = $groups[$j]
    }
}

To make things a bit clear, I have added several instructions to the loop to see what’s happening in each iteration:

$users = @(
    "user1"
    "user2"
    "user3"
)

$groups = @(
    "group1"
    "group2"
    "group3"
)

for ($i = 0; $i -lt $users.Count;$i++)
{
    Write-Host "Outerloop iteration number $i (users)"
    $userLooping = $users[$i]
    for ($j = 0; $j -lt $groups.Count;$j++)
    {
        $groupLooping = $groups[$j]
        Write-Host " -Innerloop iteration number $j (groups)"
        Write-Host "  Value of i is $i (user index) which corresponds to $userLooping"
        Write-Host "  Value of j is $j (group index) which corresponds to $groupLooping"
    }
}

This outputs the following:

Now, we just change Write-Host “Adding $userLooping to $groupLooping” for the corresponding code needed to add a user to a security group in PS:

Add-ADGroupMember -Identity $groupLooping -Members $userLooping -Verbose

We can also add a try and catch statement to handle errors. This would be the full code:

$users = @(
    "user1"
    "user2"
    "user3"
)

$groups = @(
    "group1"
    "group2"
    "group3"
)

for ($i = 0; $i -lt $users.Count;$i++)
{
    $userLooping = $users[$i]
    for ($j = 0; $j -lt $groups.Count;$j++)
    {
        $groupLooping = $groups[$j]
        try{
            Add-ADGroupMember -Identity $groupLooping -Members $userLooping -Verbose
        }
        catch{
            "An error occurred that could not be resolved."
        }
    
    }
}

| Theme: UPortfolio