Solved

Active Directory C# help

Hello All,

Writting a new C# program to replace a very old VBS file. Pretty much the program will go through our AD and get all the users and their emails and put it in a CSV file. I found some basic code and ran it and I think it worked because I saw a huge list in the console but when it was finished it closed and gave me an error.

ERROR
System.ArgumentOutOfRangeException was unhandled
Message="Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: index"
Source="mscorlib"
ParamName="index"
StackTrace:
at System.Collections.ArrayList.get_Item(Int32 index)
at System.DirectoryServices.ResultPropertyValueCollection.get_Item(Int32 index)
at ConsoleApplication4.Program.Main(String[] args) in C:\Users\jsalina\Documents\Visual Studio 2008\Projects\ConsoleApplication4\ConsoleApplication4\Program.cs:line 26
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:


Code

using System;
using System.DirectoryServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main(string[] args)
        {
            DirectoryEntry entry = new DirectoryEntry("LDAP://OU=PHF Users,DC=phf,DC=inc");

            using (DirectorySearcher ds = new DirectorySearcher(entry))
            {
                ds.PropertiesToLoad.Add("name");
                ds.PropertiesToLoad.Add("userPrincipalName");

                ds.Filter = "(&(objectClass=user))";

                SearchResultCollection results = ds.FindAll();

                foreach (SearchResult result in results)
                {
                    Console.WriteLine("{0} - {1}",
                        result.Properties["name"][0].ToString(),
                        result.Properties["userPrincipalName"][0].ToString());
                }
            }

        }
    }
}


Any thoughts on it?


P.S. That just the basic code, trying to get it to work in the console before I add the CSV file and validations. Pretty new to this type of programming.
36 answers Last reply Best Answer
More about active directory help
  1. Is there anything preventing you from using the built-in .Net objects? I wrote a user password reset module using that alone.

    http://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectory.aspx
  2. What is happening basically is that result doesn't necessarily have properties "name" and "userPrincipalName". You should check whether it has that property first before accessing the first character of that property.
  3. That is a good point Sunius, this was the the others guy who was teaching it names, I want to connect to the Ldp.exe and connect the the AD and get the exact names. Just new to this so want to ask boss to make sure I dont mess anything up in the company.

    and majestic pretty new at this, All i know from college is basic c++ and java.
  4. That is a good point Sunius, this was the the others guy who was teaching it names, I want to connect to the Ldp.exe and connect the the AD and get the exact names. Just new to this so want to ask boss to make sure I dont mess anything up in the company.

    and majestic pretty new at this, All i know from college is basic c++ and java.
  5. That's fine. Was just pointing out that I didn't have to do any custom LDAP parsing or building my own AD interaction objects. Just keep in mind that you'll only have permissions to do what the .Net machine account has rights to do within AD. I would strongly suggest you set up an account with which to impersonate for AD interaction even if it's a user with only read rights.
  6. Just got into the ldp and my names were wrong changed them but getting same errors between lines 26-28
  7. Here's the current code that is giving me an error. Just want it to work so I can move on and code the other things I need.

    
    using System;
    using System.DirectoryServices;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication4
    {
        class Program
        {
            static void Main(string[] args)
            {
                DirectoryEntry entry = new DirectoryEntry("LDAP://OU=PHF Users,DC=phf,DC=inc");
    
                using (DirectorySearcher ds = new DirectorySearcher(entry))
                {
                    ds.PropertiesToLoad.Add("cn");
                    ds.PropertiesToLoad.Add("mail");
    
                    ds.Filter = "(&(objectClass=user))";
    
                    SearchResultCollection results = ds.FindAll();
    
                    foreach (SearchResult result in results)
                    {
                        Console.WriteLine("{0} - {1}",
                            result.Properties["cn"][0].ToString(),
                            result.Properties["mail"][0].ToString());
                    }
    
                }
    
                
    
            }
        }
    }
    
  8. Your problem is that you're assuming a state that isn't true by trying to go for the first element in the Properties collection when doing as you have done clearly doesn't have a first element. You can dig in and find out this info for yourself and I highly recommend it. Debug the result object to see what the Properties collection looks like and adjust your code accordingly.

    If the Properties collection looks nothing like you'd expect then your premise about how that object works is wrong and you'll need to examine why.
  9. I am so confused, let me try to walk through the code and see if I understand it correctly.

    1)We open PHF Users directory in the AD and set that path to entry.
    2)We create a search of that directory using ds.
    3)We then say we only want to Users Name and Email and set a filter to only grab Users
    4)Then we set a search off all the data and put into results
    5)Go through all the results only pulling out the CN and MAIL categories

    Are you saying that the results are pulling every single category not just the CN and MAIL? (ie. accountExpires,badPasswordTime,badPwdCount......ect)
  10. I'm saying you're treating your 5th step in a way that's not meshing with how the results object actually works. You need to hook up a debugger and dig into the Properties collection to see how that object is being populated, if at all, and to adjust your code accordingly. Maybe the key name is different, maybe there is no element 0, etc. These are things that will become evident once you hook up a debugger.
  11. ok bare with me, I am pretty new at this debugging. Found the results and PropertiesLoaded and its saying its a string[3], [0]="cn" [1]="mail" and [2] ="ADsPath"(which idk what that is) Could this be the problem?
  12. If you put a quick watch on "result.Properties["cn"]" what are its members?
  13. so many collapsable menus, i went to:

    result->Properties->PropertyName->non-public members->["cn"]->value->base->non-public members->list->non-public members->_items->
    [0] "vault system"
    [1] null
    [2] null
    [3] null

    was that totally useless?
  14. when i hover over result.Properties["cn"][0].ToString(), the result says null on the little drop down, if it was working correctly I am guessing it would have a name in it right?
  15. Have you tried chopping off .ToString()?
  16. yup, i got this code from this guy http://blogs.msdn.com/b/kaevans/archive/2011/07/04/querying-active-directory.aspx

    exactly what i want to do, but mine doesnt work....
  17. Ok I got rid of that other code and followed another coder on YouTube, his code seems to work, getting all the names, but when i try to add the mail component it errors, gonna work on in a little and ill be back
  18. 
            static void Main(string[] args)
            {
                var dc = new DirectoryContext(DirectoryContextType.Domain);
    
                var d = Domain.GetDomain(dc);
    
                var s = d.FindDomainController().GetDirectorySearcher();
    
                s.Filter = "(&(objectClass=user))";
    
                var f = s.FindOne();
    
                Console.WriteLine(f.Path);
                Console.WriteLine(f.Properties["cn"][0]);
                Console.WriteLine(f.Properties["mail"][0]);
    
                Console.ReadLine();
            }
    


    This works fine for me. Perhaps try getting your searcher object using this method instead?
  19. what reference did u add to get directory context?
  20. System.DirectoryServices.ActiveDirectory
  21. Dont have that in my references =/
  22. So add it. As long as you ref to System.DirectoryServices you can declare using System.DirectoryServices.ActiveDirectory.
  23. the mail is still give me that same error
  24. Are you sure that property exists in that domain? As in can you go to a domain controller, open up AD and view a user to see its mail entry?
  25. I got my other code running find for user names, need to just get the mail working adn exporting the info to a CSV file, my next steps
  26. Yup, have the ldp open and looking at a user and they have a mail: xxxxxxx@xxxxx.org
  27. Well, it showed up earlier when you spit out the results of Properties. What if you drill into it like you did with cn?
  28. it not even just mail, any 2nd object i try to pull same error, only seems cn works
  29. heres the new code btw

    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.DirectoryServices;
    using Microsoft.Office.Interop.Excel;
    using System.DirectoryServices.ActiveDirectory;
    
    
    namespace EmailListing
    {
        class Program
        {
            static void Main(string[] args)
            {
              
    
                DirectoryEntry adFolderObject = new DirectoryEntry("LDAP://OU=PHF Users,DC=phf,DC=inc");
    
                DirectorySearcher adSearchObject = new DirectorySearcher(adFolderObject);
    
                adSearchObject.SearchScope = SearchScope.Subtree;
    
                adSearchObject.Filter = "(&(ObjectClass=user)(!description=Built-in*))";
    
                foreach (SearchResult adObject in adSearchObject.FindAll())
                {
                    Console.WriteLine("cn={0}", adObject.Properties["cn"][0]);
                   // Console.WriteLine("co={0}", adObject.Properties["co"][0]);
                   
                }
    
                Console.WriteLine();
                Console.ReadLine();
            }
        }
    }
    
  30. Best answer
    Did you try digging into name like you did with cn? Also, double check what permissions are setup as AD may not be sending that info as you may not be allowed to see anything except names.
  31. well done, i dug into it and its only bringing in 32 fields and mail isnt one of them. Now how do we get all the fields brought in lol
  32. You'll need to research that one. Google is your friend.
  33. I found stuff on active direct schema, do I need to add a new using class for it? some of the schema options arent showing up
  34. That's beyond my expertise, mate.
  35. alright thanks a lot for everything else
  36. Best answer selected by laserpp.
Ask a new question

Read More

Programming C# Active Directory Apps