jawhitmoyer
asked on
I need to delete a user from Domain Users in AD using VB
For security reasons, I need to delete a user from the Domain Users group in AD. I already have them in an OU with their Primary Group set to a special group.
Here's the code I am using to create them, and assign them to the new group.
Private Sub AddUserToAD()
'This code adds a NEW USER to a specified OU.
'
'Useful in constructing LDAP "Paths":
'cn = Computer, Contact, Container, Group, Print Queue, and User objects
'ou = Organizational Unit
'dc = Domain controller name (example dc=mydomain,dc=com for mydomain.com)
'o = Domain name
'First, connecto to the Active Directory.
Dim sDomain As String = "gafcon"
Dim sUsername As String = "admin"
Dim sPassword As String = "password"
Dim dom As DirectoryEntry = New DirectoryEntry("LDAP://" & sDomain, sUsername, sPassword)
'Connect to the specific OU
Dim ouToAddTo As DirectoryEntry = dom.Children.Find("OU=SHAR EPOINT")
'Use the Add method to add a user in an organizationalUnit.
Dim newUser As DirectoryEntry = ouToAddTo.Children.Add("CN =Cliff", "User")
'Set the core AD properties
' Pre-Windows 2000 Name
newUser.Properties("sAMAcc ountName") .Value = "Cliff"
' User Logon Name
newUser.Properties("userPr incipalNam e").Add("C liff@gafco n.local")
' Email
newUser.Properties("mail") .Value = "Cliff@gafcon.local"
' First Name
newUser.Properties("givenN ame").Add( "Cliff")
' Initials
newUser.Properties("initia ls").Add(" CS")
' Last Name
newUser.Properties("sn").A dd("West")
' Display Name
newUser.Properties("displa yName").Ad d("Cliff West")
' Description
newUser.Properties("descri ption").Ad d("Added by " & _
System.Security.Principal. WindowsIde ntity.GetC urrent().N ame)
'Create the account
newUser.CommitChanges()
'set the password for the new user
newUser.Invoke("setPasswor d", "password")
Dim userACFlags As Object = newUser.Properties("userAc countContr ol").Value
newUser.Properties("userAc countContr ol").Value = userACFlags Or &H200 Or &H10000 Xor &H2
'Commit the changes
newUser.CommitChanges()
sDomain = "OU=SHAREPOINT,DC=GAFCON,D C=LOCAL"
Dim grp As DirectoryEntry = New DirectoryEntry("LDAP://" & sDomain, sUsername, sPassword)
Dim addMe As DirectoryEntry = grp.Children.Find("CN=Extr anet", "group")
addMe.Properties("member") .Add(newUs er.Propert ies("disti nguishedNa me").Value )
addMe.CommitChanges()
'Dim addMe As DirectoryEntry = grp.Children.Find("CN=Extr anet", "group")
If Not addMe.Properties.Contains( "PrimaryGr oupToken") Then
addMe.RefreshCache(New String() {"PrimaryGroupToken"})
End If
newUser.Properties("Primar yGroupID") .Value = addMe.Properties("PrimaryG roupToken" ).Value
newUser.CommitChanges()
End Sub
Here's the code I am using to create them, and assign them to the new group.
Private Sub AddUserToAD()
'This code adds a NEW USER to a specified OU.
'
'Useful in constructing LDAP "Paths":
'cn = Computer, Contact, Container, Group, Print Queue, and User objects
'ou = Organizational Unit
'dc = Domain controller name (example dc=mydomain,dc=com for mydomain.com)
'o = Domain name
'First, connecto to the Active Directory.
Dim sDomain As String = "gafcon"
Dim sUsername As String = "admin"
Dim sPassword As String = "password"
Dim dom As DirectoryEntry = New DirectoryEntry("LDAP://" & sDomain, sUsername, sPassword)
'Connect to the specific OU
Dim ouToAddTo As DirectoryEntry = dom.Children.Find("OU=SHAR
'Use the Add method to add a user in an organizationalUnit.
Dim newUser As DirectoryEntry = ouToAddTo.Children.Add("CN
'Set the core AD properties
' Pre-Windows 2000 Name
newUser.Properties("sAMAcc
' User Logon Name
newUser.Properties("userPr
newUser.Properties("mail")
' First Name
newUser.Properties("givenN
' Initials
newUser.Properties("initia
' Last Name
newUser.Properties("sn").A
' Display Name
newUser.Properties("displa
' Description
newUser.Properties("descri
System.Security.Principal.
'Create the account
newUser.CommitChanges()
'set the password for the new user
newUser.Invoke("setPasswor
Dim userACFlags As Object = newUser.Properties("userAc
newUser.Properties("userAc
'Commit the changes
newUser.CommitChanges()
sDomain = "OU=SHAREPOINT,DC=GAFCON,D
Dim grp As DirectoryEntry = New DirectoryEntry("LDAP://" & sDomain, sUsername, sPassword)
Dim addMe As DirectoryEntry = grp.Children.Find("CN=Extr
addMe.Properties("member")
addMe.CommitChanges()
'Dim addMe As DirectoryEntry = grp.Children.Find("CN=Extr
If Not addMe.Properties.Contains(
addMe.RefreshCache(New String() {"PrimaryGroupToken"})
End If
newUser.Properties("Primar
newUser.CommitChanges()
End Sub
Jim, you are almost there. But first you need to understand a couple of things. Let say you want SecurityGroupA to replace "Domain Users" primary group for UserA. You're allowed to do that if SecurityGroupA already has UserA as its member. Other than that you'll get exception. So essentially your code needs to check whether the above condition is satisfied or manually set UserA to be SecurityGroupA's member. Then the next step is to bind to "Domain Users" group and manually remove UserA from its "member" attribute.
Pseudo code:
securityGroupA = getGroupFromAD()
If userA is not a member of securityGroupA Then
add UserA as member of securityGroupA
End If
Replace "Domain User" with securityGroupA
domainUsers = getGroupFromAD()
Remove UserA from domainUsers membership.
Please try that and let me know if you have any problem.
Pseudo code:
securityGroupA = getGroupFromAD()
If userA is not a member of securityGroupA Then
add UserA as member of securityGroupA
End If
Replace "Domain User" with securityGroupA
domainUsers = getGroupFromAD()
Remove UserA from domainUsers membership.
Please try that and let me know if you have any problem.
ASKER
By default all users are created in the Domain Users group. That's why I tought I would just need the code above to remove them. I get an error because I am not finding the group in AD. Is Domain Users group in the root of AD, or do I need to look for it something like "CN=USERS"?
Ok, you have the code to replace primary group with another group and you know how to remove a user's membership from a group. Now I'll tell you how to get a user's primary group. "Domain Users" group as the default primary group for all user objects exists in every domain in the forest. That means, if you have multiple domains in your AD forest you can't exactly tell what "Domain Users" group map to what user without knowing where the user comes from. The "shortest way" (and the best performance can be achieved) to determine the primary group of a user is to build an sid bind string for the group object from the domain rid component of the user's sid and the PrimaryGroupID attribute on the user object. Then use the sid string to bind to the group using DirectoryEntry class.
I guess, there's no easy way to explain this without actually posting some code. I have the code handy and it does exactly what you need, but...the code is written in c# and it's involving some pointer operations. For that I'm not sure how you're going to convert it to VB.NET. But I have something for your consideration:
1. Compile the c# code into a separate assembly and call it from your VB.NET project.
2. If point 1. is not an option, throw another question to VB.NET TA about the code conversion problem, someone might be able to show you a workaround
3. Forget about the code, open adsiedit via mmc snap-ins and copy the "distinguishedName" attribute of the default "Domain Users" group and hard code it in your code (this won't be so simple if you have multiple domains).
4. Comeback here, there's another workaround. No pointer operation, whatsoever but I don't have it handy and I can't promise you'll see any good performance from it. Another bad news is you have to write and test more lines of code if you want to go with this.
Please reply and let me know which one are you able to go with.
I guess, there's no easy way to explain this without actually posting some code. I have the code handy and it does exactly what you need, but...the code is written in c# and it's involving some pointer operations. For that I'm not sure how you're going to convert it to VB.NET. But I have something for your consideration:
1. Compile the c# code into a separate assembly and call it from your VB.NET project.
2. If point 1. is not an option, throw another question to VB.NET TA about the code conversion problem, someone might be able to show you a workaround
3. Forget about the code, open adsiedit via mmc snap-ins and copy the "distinguishedName" attribute of the default "Domain Users" group and hard code it in your code (this won't be so simple if you have multiple domains).
4. Comeback here, there's another workaround. No pointer operation, whatsoever but I don't have it handy and I can't promise you'll see any good performance from it. Another bad news is you have to write and test more lines of code if you want to go with this.
Please reply and let me know which one are you able to go with.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I can definitely work with the C#. You have been a big help.
Thanks!
Thanks!
ASKER
sDomain = "DC=GAFCON,DC=LOCAL"
Dim grp2 As DirectoryEntry = New DirectoryEntry("LDAP://" & sDomain, sUsername, sPassword)
addMe = grp2.Children.Find("CN=Dom
addMe.Properties("member")
addMe.CommitChanges()