ASP.NET and Directory Services...again RRS feed

  • Question

  • User701884916 posted
    Hi! How do I find ALL users in AD? I've allready managed to extract the info I need about a user, supplying a sAMAccountName. Now I'm trying to retrieve all users. It seems like, eventhou i supply a LDAP-connectionstring, it's not nessesary?? Meaning that I don't need to set anything else but the root...?? Then it's the filter... I've tried: filter = "(&(ObjectClass=user)(sAMAccountName=*))" and: filter = "(&(ObjectClass=user)) and: filter = "(&(ObjectClass=users)) ...any ideas...anybody? Mabye my problem lies somewhere else. This functionality is supplied by a helperclass (based on timetracker example), and I expect a arraylist of users or, if failure, nothing. And I get nothing... Thanks! /bix
    Friday, August 15, 2003 4:14 AM

All replies

  • User-567995596 posted
    Hey Bix, I think you want to use objectClass=Person. Here is an example of how to write a file that contains a list of all Active Directory Users. You should only need to change the LDAP host and you may need to change the path to where the file gets written to: GetAllUsers.cs ---------------- using System; using System.DirectoryServices; using System.IO; class GetAllUsers { static void Main (string[] args) { DirectoryEntry entry = new DirectoryEntry("LDAP://host"); DirectorySearcher mySearcher = new DirectorySearcher(entry); mySearcher.Filter = ("(objectClass=Person)"); FileStream file = new FileStream("E:\\persons.txt", FileMode.OpenOrCreate, FileAccess.Write); StreamWriter sw = new StreamWriter(file); sw.Write("Active Directory Users\n"); sw.Write("===========================================\n"); foreach(SearchResult resEnt in mySearcher.FindAll()) { sw.Write(resEnt.GetDirectoryEntry().Name.ToString() + "\n"); } sw.Close(); file.Close(); } } Let me know if it helps. Joe Willy
    Saturday, August 16, 2003 10:17 PM
  • User1354132231 posted
    I previously shared a routine that will allow you to easily search the Directory and return users as a DataSet for binding later. It uses caching to speed subsequent requests. Read about it here (called FindUsers()): <post>163706</post> The correct ldap filter to find all users is either: "(objectClass=user)" or even better for indexing "(&(objectClass=user)(objectCategory=person))". The first one will work fine, but can be a little slow since 'objectClass' property is not indexed, while 'objectCategory' is. However, you will need to specify both instead of just "(objectCategory=person)" if you want to avoid returning contacts as well as users.
    Sunday, August 17, 2003 11:23 AM
  • User701884916 posted
    Ok... Nothing I do seems to work... I have a function that is supposed to return an arraylist of user-objects, but i get nothing... I've managed to catch the exception: "A referral was returned from the server" What's this? I'm starting to believe that my LDAP-string is faulty, but it works just fine when I look for a single user. Any advice? Thanks: Bix
    Tuesday, August 19, 2003 10:25 AM
  • User1354132231 posted
    Usually that error is related to a faulty LDAP string as you said. Post some of your code if you can. If you use that FindUsers() function I mentioned earlier with same ldap query and connection string, what does it return? That can help you pinpoint if it is your code or just the connection string. The fact that it works for single user is perplexing, and also a reason why I would want to see your code. I would suspect your code at this point since a faulty connection string would never return results.
    Tuesday, August 19, 2003 1:30 PM
  • User701884916 posted
    Ok dunnry. I've tested your FindUsers() function, after a translation to vb (I used the online service at http://www.aspalliance.com/aldotnet/examples/translate.aspx). I get nothing in return from FindUsers(). This is the function that works: Public Shared Function getUser(ByVal identification As String) As MyUser If ConfigurationSettings.AppSettings(Web.Global.CfgKeyUserAcctSource) = "ActiveDirectory" Then ' Setup the filter identification = identification.Substring(identification.LastIndexOf("\") + 1, identification.Length - identification.LastIndexOf("\") - 1) '_filter is declared as a classvariable: ' Private Const _filter As String = "(&(ObjectClass=user)(SAMAccountName={0}))" Dim userNameFilter As String = String.Format(_filter, identification) ' Get a Directory Searcher to the LDAPPath Dim searcher As New DirectorySearcher() If searcher Is Nothing Then Return Nothing End If ' Add the propierties that need to be retrieved searcher.PropertiesToLoad.Add("user") searcher.PropertiesToLoad.Add("mail") searcher.PropertiesToLoad.Add("givenName") searcher.PropertiesToLoad.Add("sn") searcher.PropertiesToLoad.Add("userPassword") searcher.PropertiesToLoad.Add("department") ' Set the filter for the search searcher.Filter = userNameFilter Try ' Execute the search Dim search As SearchResult = searcher.FindOne() If Not (search Is Nothing) Then Dim JJ As MyUser JJ = New MyUser(identification) JJ.DisplayeNamn = SearchResultProperty(search, "sn") JJ.DisplayfNamn = SearchResultProperty(search, "givenName") JJ.DisplayMail = SearchResultProperty(search, "mail") JJ.DisplayPwd = SearchResultProperty(search, "userPassword") JJ.DisplayKontor = SearchResultProperty(search, "department") Return JJ Else Return Nothing End If Catch End Try Else Return Nothing End If End Function Here's the code for SearchResultProperty: Public Shared Function SearchResultProperty(ByVal sr As SearchResult, ByVal field As String) As [String] If Not (sr.Properties(field) Is Nothing) Then Return CType(sr.Properties(field)(0), [String]) End If Return Nothing End Function 'SearchResultProperty I've noticed that there is NO DirectoryEntry and NO LDAP-path in the working function. What I've done sofar is to alter the working getUser() function into a findAllUsers() function. the returnvalue usersCollection inherits ArrayList. This function returns nothing,i.e. not working as it supposed to... Public Shared Function findAllUsers() As usersCollection Dim allUsers As usersCollection Dim JJ As MyUser Dim searcher As New DirectorySearcher() If searcher Is Nothing Then Return Nothing End If ' Add the propierties that need to be retrieved searcher.PropertiesToLoad.Add("mail") searcher.PropertiesToLoad.Add("givenName") searcher.PropertiesToLoad.Add("sn") searcher.PropertiesToLoad.Add("userPassword") searcher.PropertiesToLoad.Add("department") searcher.PropertiesToLoad.Add("sAMAccountName") ' Set the filter for the search searcher.Filter = "(&(objectClass=user)(objectCategory=person))" Try Dim res As SearchResult Dim search As SearchResultCollection = searcher.FindAll() For Each res In search JJ = New MyUser(SearchResultProperty(res, "sAMAccountName")) JJ.DisplayeNamn = SearchResultProperty(res, "sn") JJ.DisplayfNamn = SearchResultProperty(res, "givenName") JJ.DisplayMail = SearchResultProperty(res, "mail") JJ.DisplayPwd = SearchResultProperty(res, "userPassword") JJ.DisplayKontor = SearchResultProperty(res, "department") allUsers.Add(JJ) Next Catch Return Nothing End Try Return allUsers End Function In a perfect world, this would work :-) can you find where I'm failing? thanks! Bix
    Wednesday, August 20, 2003 5:39 AM
  • User1354132231 posted
    You are right, the code you have shown me should be working as far as I can tell without running it. But... you could be getting an error from your SearchResultProperty() method and you would never know it. To debug this, step into the call right after the .FindAll() call. Then check what search.Count returns to see if you are getting any results or it is blowing up on one of the users. If you are getting a .Count > 0, then you need to catch the Exception in your Catch statement and inspect it. If you don't specify a SearchRoot for the DirectorySearcher, it will default to the root domain of the machine it is running on. You can figure out what this would be if you know the FQDN of your IIS machine. For instance, IISServer1.childdomain.mydomain.com would be connecting to the equivalent DirectoryEntry at "LDAP://DC=childdomain,DC=mydomain,DC=com". You can check this by debugging the code after the FindOne() or FindAll() call and inspecting the SearchRoot property. To be more efficient, you should create a DirectoryEntry and set its base to where you want to start your search and pass that as the SearchRoot to the DirectorySearcher. You are actually searching the entire domain when you don't specify one which could be very slow if you have a large # of objects in the domain.
    Wednesday, August 20, 2003 8:33 AM
  • User701884916 posted
    Ok... I get 106 matches in search so the FindAll() works. What confuses me is that i expect a number from sAMAccountName cause that's the login at our company. I get "Administrator" and "Guest" and then a crasch with the error: "Length cannot be less than zero. Parameter name: length" It's this line that crasches the app: JJ = New MyUser(SearchResultProperty(res, "sAMAccountName")) and it crasches on the "guest"-account. I think I have identified the cause, MyUser expects a "domain\user", and it strips the domain from the string, leaving just a number in stringformat. But if i give the object "Guest" then it will crasch... Isn't the sAMAccountName the name used when logging in to the system? All I need now is the schema name of the "User Logon Name" in AD. By the way, why is it called SAMaccountname, I'm on w2k server?
    Wednesday, August 20, 2003 9:58 AM
  • User701884916 posted
    I've solved it! Check if sAMAccountName is numeric. Finally, I'm ready to move on! Thankyou Dunnry!! regards: Bix
    Wednesday, August 20, 2003 10:42 AM
  • User1354132231 posted
    Isn't the sAMAccountName the name used when logging in to the system? All I need now is the schema name of the "User Logon Name" in AD. By the way, why is it called SAMaccountname, I'm on w2k server? The sAMAccountName is used when logging in as your username. Additionally, you can use userPrincipalName (user@domain.com). The sAMAccountName is supposed to be for compatibility, but in reality, users like typing 'Joe' instead of 'Joe@domain.com' when they login to their computer. That original method that I suggested (FindUsers()) should not have failed on this issue then as you have described it. I suspect that something in your conversion from C# to VB.NET failed instead. I am glad your issue is worked out. Good luck.
    Wednesday, August 20, 2003 12:57 PM
  • User-31526489 posted

    Create Active Directory Service using WCF – Accusing AD Functions using WCF Services – AD Services

    Wednesday, December 9, 2009 8:45 AM