Hey, Scripting Guy! How Do I Remove All Group Members in Active Directory?

Hey, Scripting Guy! How Do I Remove All Group Members in Active Directory?

  • Comments 9
  • Likes

Hey, Scripting Guy! Question

Hey Scripting Guy! I have several groups created in Active Directory whose membership has changed dramatically. Rather than go through a long list of users and try to manually clean up the list, I would like to just delete all the users from the group so that I can later add the newly approved members to the group. I have checked around, and there does not seem to be a deleteall method from a directory entry object in Windows PowerShell. Am I missing it?

-- JD

 

Hey, Scripting Guy! Answer

Hello JD,

This week I (Ed) am speaking at Microsoft TechReady in Seattle. TechReady is kind of like TechEd except it is for Microsoft employees only. I have been attending lots of sessions, completing hands-on labs, and am generally friedor maybe broiled (it’s very hot here right now). The bad things about conferences such as this is that it always seems that there are two sessions that both sound good that are scheduled at the same time. As a result I end up missing some really cool session that sounds great. Of course, all the sessions are recorded, and all the Microsoft PowerPoint decks are posted on a SharePoint site, but it is not quite the same as attending the live session. When I gather around a lunch table and chat with friends and co-workers, I always ask about the sessions they attended. At times my choice is confirmed, but occasionally I feel as if I really missed out on something.

JD, I do not want you to miss out on anything, so I wrote the Remove-AllGroupMembers.ps1 script for you. One thing you will notice is there is no deleteall method, so you did not overlook a method. In fact, we pulled out a method we used in VBScript (putex) to perform the magical deletion you required. The complete Remove-AllGroupMembers.ps1 script is seen here.

Remove-AllGroupMembers.ps1

Param(
   [string]$group,
   [string]$ou,
   [string]$domain,
   [switch]$whatif,
   [switch]$help
) #end param

Function Get-ScriptHelp
{
 "Remove-AllGroupMembers.ps1 removes all members of a group"
 "Remove-AllGroupMembers.ps1 -group cn=mygroup -ou ou=myou -domain 'dc=nwtraders,dc=com'"
 "Remove-AllGroupMembers.ps1 -group cn=mygroup -ou ou=myou -domain 'dc=nwtraders,dc=com' -whatif"
} # end function Get-ScriptHelp

Function Remove-AllGroupMembers
{
 Param(
   [string]$group,
   [string]$ou,
   [string]$domain
 ) #end param
 $ads_Property_Clear = 1
 $de = [adsi]"LDAP://$group,$ou,$domain"
 $de.putex($ads_Property_Clear,"member",$null)
 $de.SetInfo()
} # end function Remove-AllGroupMembers

Function Get-Whatif
{
  Param(
   [string]$group,
   [string]$ou,
   [string]$domain
 ) #end param
 "WHATIF: Remove all members from $group,$ou,$domain"
} #end function Get-Whatif

# *** Entry Point to script ***

if(-not($group -and $ou -and $domain))
  { throw ("group ou and domain required") }
if($whatif) { Get-Whatif -group $group -ou $ou -domain $domain ; exit }
if($help) { Get-Scripthelp ; exit }
"Removing all members from $group,$ou,$domain"
Remove-AllGroupMembers -group $group -ou $ou -domain $domain

The Remove-AllGroupMembers.ps1 script begins by creating several command-line parameters. To do this, the Param statement is used. The first three parameters are strings: the group name, the organizational unit name, and the domain name. These will need to be supplied to the script in the form of cn=groupname. You could modify the script to change this requirement, but it rapidly becomes rather complicated in trying to figure out how many levels down a group may reside. The last two parameters are switched parameters: the whatif and the help parameters. The Param section of the script is seen here:

Param(
   [string]$group,
   [string]$ou,
   [string]$domain,
   [switch]$whatif,
   [switch]$help
) #end param

I consider it a best practice when a script requires command-line parameters to include help information to illustrate how to actually use the script. This is useful not only for the users of your script, but also for you as well when you approach a script several months after it has been written. In Windows PowerShell 2.0, script help integrates with the Get-Help cmdlet, and can be created using stylized tags. But in Windows PowerShell 1.0, you are limited to displaying strings to the command line. By creating minimal help for your scripts now, you are preparing yourself to migrate the script to the more robust script help available in Windows PowerShell 2.0.

In the Get-ScriptHelp function, a short description of the script is displayed, as well as two representative command-line examples:

Function Get-ScriptHelp
{
 "Remove-AllGroupMembers.ps1 removes all members of a group"
 "Remove-AllGroupMembers.ps1 -group cn=mygroup -ou ou=myou -domain 'dc=nwtraders,dc=com'"
 "Remove-AllGroupMembers.ps1 -group cn=mygroup -ou ou=myou -domain 'dc=nwtraders,dc=com' -whatif"
} # end function Get-ScriptHelp

To remove all members of a group you can use the Remove-AllGroupMembers function. Members of a group are seen here:

Image of akk members of a group

 

The function begins with three parameters: group, ou, and domain. Instead of listing these parameters in a long line in the Function declaration statement, I decided to move them inside the function script block and use the Param statement. This is exactly the same thing, but I consider it a best practice when declaring more than one or two parameters. This is because it makes it easier to read the script. In addition, it will set you up to make an easier migration to Windows PowerShell 2.0 because of the rich parameter statements that become available. The Function statement and the Param statement for the Remove-AllgroupMembers function is seen here:

Function Remove-AllGroupMembers
{
 Param(
   [string]$group,
   [string]$ou,
   [string]$domain
 ) #end param

It is time get to the nuts and bolts of the Remove-AllGroupMembers function. First, a variable named $ads_Property_Clear is created and set to a value of 1. The number 1 is the value from the ADS_PROPERTY_OPERATION_ENUM ADS_PROPERTY_CLEAR constant. When this is set to 1, it instructs the directory service to remove all property values from the object:

 $ads_Property_Clear = 1

When you need to work with an object in Active Directory, it generally involves connecting to the object first. To do this, you use the [adsi] type accelerator, specify the protocol (LDAP), and supply the path to the object. This is seen here: 

 $de = [adsi]"LDAP://$group,$ou,$domain"

To remove the members of the group, you use the putex method, which uses one of the ADS_PROPERTY_OPERATION_ENUM values seen in Table 1 in the first position of the method call.

Table 1 ADS_PROPERTY_OPERATION_ENUM Values

Enumeration name

Enumeration value

  ADS_PROPERTY_CLEAR   

 1

  ADS_PROPERTY_UPDATE  

 2

  ADS_PROPERTY_APPEND  

 3

  ADS_PROPERTY_DELETE  

 4

 

In the second position of the putex method call, you list the property you wish to work with. The third position must be filled out, but is ignored when you are clearing the contents of the property. After the changes have been made, you call the SetInfo method. This is all seen here:

 $de.putex($ads_Property_Clear,"member",$null)
 $de.SetInfo()
} # end function Remove-AllGroupMembers

When you have a script that deletes things, it is a best practice to implement a whatif function. To do this, you create use the same parameters that are supplied to the Remove-AllGroupMembers function and display the string that gets put together. This is helpful in that it provides confirmation information about what the script is attempting to accomplish. The Get-Whatif function is seen here:   

Function Get-Whatif
{
  Param(
   [string]$group,
   [string]$ou,
   [string]$domain
 ) #end param
 "WHATIF: Remove all members from $group,$ou,$domain"
} #end function Get-Whatif

You now arrive at the entry point to the script. Because the script will fail if it does not receive the group name, ou name, and domain name, use an if statement to check for the presence of the values from the command line. To do this, you use the not operator and the and operator as seen here. If the values are not available, the throw command is used to raise an error. This is seen here:

if(-not($group -and $ou -and $domain))
  { throw ("group ou and domain required") }

After checking for the group, ou and domain names, you next need to see if the script was run with the whatif switch. If it was, the Get-Whatif function is called and then the script exits. This is seen here:

if($whatif) { Get-Whatif -group $group -ou $ou -domain $domain ; exit }

If the script is run with the help switch, it calls the Get-ScriptHelp function and exits:

if($help) { Get-Scripthelp ; exit }

After all the preliminary command-line commands have been checked, it is time to call the Remove-AllGroupMembers function. This is seen here:

"Removing all members from $group,$ou,$domain"
Remove-AllGroupMembers -group $group -ou $ou -domain $domain

Well, RD, we hope you have enjoyed this discussion on removing all users from a group. If you want to keep up with all the things that are happening on the Script Center, you can follow us on Twitter. You can also join the Scripting Guys group on Facebook and find lots of other friends who are interested in scripting. If you ever get stuck again while you are working on a script, post your question on the Official Scripting Guys Forum. There are some really smart scripters who hang out there. Join us tomorrow as we continue our discussion of Active Directory scripting. Until then, peace!

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Windows PowerShell is great, but there is a much easier way....

    dsget group "CN=GroupName,OU=Groups,DC=Domain,DC=com" -members | dsmod group "CN=GroupName,OU=Groups,DC=Domain,DC=com" -rmmbr

  • I'm getting 0x8000500 errors on the putex and setinfo, although I'm a domain admin.

    I used Michael his alternative.

    Michael,

    Your method is easier in coding, but it takes (much) longer executing time, because it removes the users out of the membership one by one; while Ed and Craig their method empties the member attribute in one action. With large groups, it can count ;)

  • I ended up here because there is no neat little cmdlet. Then I wondered why I couldn't pipe the members of the group back to itself to remove them, which seems to work. GetADGroupMember "GroupName" | ForEach-Object {Remove-ADGroupMember "GroupName" $_ -Confirm:$false} Is there anything obvious I'm missing? It kind of seems too easy to be right.

  • Why not use Set-ADObject -Filter { name -eq "Group Name" } -Clear member

  • Neat solution in previous comment, although Set-ADObject doesn't seem to have the Filter parameter.
    In ended up with using 'Get-ADGroup | Set-ADObject -Clear member'.

  • DMoenks, thank you for that. I too was trying to use get-adgroupmember and pipe it to remove-adgroupmember. Your way is much quicker and easier. That is exactly what I needed.

  • thank you

  • > Neat solution in previous comment, although Set-ADObject doesn't
    > seem to have the Filter parameter. In ended up with using
    > 'Get-ADGroup | Set-ADObject -Clear member'.

    Set-ADObject has the -filter parameter. It works perfectly.

  • Hello, I get the following 2 errors:
    The following exception occurred while retrieving member "putex": "There is no such object on the server.
    The following exception occurred while retrieving member "SetInfo": "There is no such object on the server.