Active Directory vb.net (Visual Studio 2005) question...

Hi,

I am creating user accounts in Active Directory via vb.net. Once the account is created I need to assign permissions to the "homedirectory" that I have assigned in Active Directory. I have access to the Active Directory name attributes but I need to convert these to a NT account format ( DOMAIN\AccountName ) to add security via the DirectorySecurity AddAccessRule method.

Is there a way to instantiate the NTAccount class from an Active Directory Entry?

I'm not sure if this is necessary I just found that class and it looked like a good fit; a simple routine to create the DOMAIN\AccountName from the Directory Entry attributes like cn might also suffice.

Thanks much,

Steve

[1171 byte] By [seiden] at [2008-1-10]
# 1

The simplest method that I have found is;

NTAccount(identity)

where identity is equal to the user name (cn). The domain is picked up automatically when I use this statement and I do not have to do a bunch of formatting to obtain the domain in the correct format from Active Directory.

Steve

seiden at 2007-10-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 2

Can I see your VB.net code for creating AD users? It would be very helpful. Thnaks.

Hobbs at 2007-10-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 3

Hobbs,

The code is listed below... Of course the bulk of the work to format the data and search for existing entries has already taken place.

Regards- Steve

Code Snippet

'CREATE THE STUDENT ENTRY IN ACTIVE DIRECTORY

'Create a new common name (CN) entry in the container

dsUser = cnEntry.Children.Add("CN=" & userName, "user")

If middleInitDisplay.Length > 0 Then 'This statement handles an empty middle initial value

'General Tab

dsUser.Properties.Item("initials").Value = UCase(Left(middleInitDisplay, 1))

End If

'Add user properties - organized and commented per Active Directory Users & Computers UI tool

With dsUser.Properties

'General Tab

.Item("givenname").Value = firstNameDisplay

.Item("sn").Value = lastNameDisplay

.Item("displayname").Value = displayName.Trim() 'If no middle initial is present this trim remove extra spaces

.Item("description").Value = "Student"

.Item("mail").Value = email

'Address Tab - used only for processing items

.Item("xx").Value = "xx" 'KEYs removed for security purposes (hence "xx")

.Item("xx").Value = xx

'Account Tab

.Item("userprincipalname").Value = email

.Item("sAMAccountName").Value = userName

.Item("accountexpires").Value = GetLargeInteger(expireDate64) 'idli

'Profile Tab

'.Item("profilepath").Value = "\\xx\xx$\" & userName 'Disable roaming profiles

.Item("homedrive").Value = "H:"

.Item("homedirectory").Value = "\\xx\xx$\" & userName

End With

'dsUser.Invoke("SetPassword", password) 'Early bound vs late binding below (will fail Option Strict)

With dsUser

.CommitChanges()

.NativeObject.setPassword(password)

.NativeObject.accountDisabled = False

.NativeObject.pwdLastSet = mustChangePassword

.CommitChanges()

End With

'Assign the student to the Student group

studentGroup.Add(dsUser.Path)

studentGroupEntry.CommitChanges()

'Create a mailbox for the student

cmdEM.Parameters.Clear() 'Clear out entries from the last student

cmdEM.Parameters.Add("Database", mailDB)

cmdEM.Parameters.Add("Identity", email) 'The email variable contains the User Principle Name (UPN)

cmdEM.Parameters.Add("Alias", userName) 'Specified in the format xx

cmdEM.Parameters.Add("DomainController", dnsHostFQDName) 'FQDN from rootDSE

cmdResults = ems.PipelineInvoke(cmdEM, CObj(iErrors))

For Each cmdItem In cmdResults

Console.WriteLine(cmdItem.Members("Name").Value.ToString)

Next

'Check for pipeline errors

If Not iErrors Is Nothing Then

For Each errorItem In iErrors

Console.WriteLine("Error encountered creating the mailbox: {0} for display name {1} / EmplID: {2}", errorItem.ToString, displayName, emplId)

Dim adMsg As String = ("Error encountered creating the mailbox: " & errorItem.ToString & " for display name " & displayName & " / EmplID: " & emplId)

EventLog.WriteEntry("ADStudentUpdate", adMsg, EventLogEntryType.Error)

' ADLogInstance.WriteEntry("ADStudentUpdate", adMsg, EventLogEntryType.Warning)

ADLogInstance.Close()

Next

'Verify that a mailbox was created

ElseIf cmdResults.Count < 1 Then

Console.WriteLine("Mailbox not created for display name {0} / EmplID: {1}", displayName, emplId)

Dim adMsg As String = ("Mailbox not created for display name " & displayName & " / EmplID: " & emplId)

EventLog.WriteEntry("xx", adMsg, EventLogEntryType.Error)

ADLogInstance.Close()

'If the mailbox was created update the status code of the associated account in Active Directory

Else

studentsMailBoxesCreated = studentsMailBoxesCreated + 1

dsUser.Properties.Item("xx").Value = "xx" 'KEYs removed for security purposes

dsUser.CommitChanges()

End If

seiden at 2007-10-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 4

This is great, thanks. I had it in VBscript, and some done in VB/asp.net, but this is very helpful. My data comes from SQL which is put there by another web form, so I dont have to worry about formatting really, but if you can post the search code as well that would be great. Thanks!

Hobbs at 2007-10-3 > top of Msdn Tech,Visual Basic,Visual Basic General...
# 5

I have a couple searches but this should be a example for you:

Code Snippet

'SEARCH FOR THE STUDENT BY COMMON NAME (CN) WITHIN ACTIVE DIRECTORY

Using duplSearcher As DirectorySearcher = New DirectorySearcher(cnEntry)

duplSearcher.Filter = "(&(objectCategory=person)(objectClass=user)(cn=" & userName & "))"

duplSearcher.PropertiesToLoad.Add("xx")

duplSearcher.SearchScope = SearchScope.OneLevel

Dim duplADSearchResultCollection As SearchResultCollection = duplSearcher.FindAll()

cnEntry comes from:

Code Snippet

'Create a Directory Entry and bind to the Student OU within the domain path

'A "Using" stmt is incorporated so the cnEntry is cached making subsequent searches

'faster

Using cnEntry As DirectoryEntry = New DirectoryEntry( _

"LDAP://OU=Accounts - xx," & domainPath, _

Nothing, _

Nothing, _

AuthenticationTypes.Secure) ' Default for .Net 2.0, indicated for clarity

cnEntry.RefreshCache() 'Will quickly force a bind to the directory

domainPath is built from the RootDSE:

Code Snippet

'OBTAIN ALL THE ACTIVE DIRECTORY ENTRIES FOR THE xx OU

'Obtain the directory information tree root - this eliminates hard coding domain controller names

'The rootDSE entry is left open so that the connection can be used for subsequent binds

Dim rootDSE As DirectoryEntry = New DirectoryEntry( _

"LDAP://RootDSE", _

Nothing, _

Nothing, _

AuthenticationTypes.Secure)

'Force the connection to be established to quickly bind to the directory

Dim bindTest As Object = rootDSE.NativeObject

'Obtain the domain naming context (DC=xx,DC=xx,DC=xx)

Dim domainPath As String = rootDSE.Properties("defaultNamingContext")(0)

I do a couple searches so that I'm sure that I am not putting duplicate entries out in the directory but the structure is the same for all. I am in the process of consolidating them where possible to speed up processing.
seiden at 2007-10-3 > top of Msdn Tech,Visual Basic,Visual Basic General...