Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2637
  • Last Modified:

Count AD disabled accounts C#

Greetings,
I'm using system.directoryservices.accountmanagment and c# I'm trying to programmatically count the number of disabled accounts on the network.

Here is the part of the code that I'm using to get that those numbers.
int count = 0;
UserPrincipal u  = new UserPrincipal(ctx);
PrincipalSearcher s = new PrincipalSearcher();
s.QueryFilter = u;
foreach(Principal p in u.FindAll())
{
if(u.Enabled == false)
count++;
}

// then I gon on to display count

Problem is that it always displays 0. Please help. Thanks. I eventually want to be able to programmatically find the number of lockedaccounts as well.
 
0
centem
Asked:
centem
  • 4
  • 3
1 Solution
 
Netman66Commented:
Did you try u.Disabled == True?
0
 
centemAuthor Commented:
Yes. I did. The only time I dont get a count of 0 is when I remove the if statement. In which case its just counting the number of users in AD.
0
 
Russell_VenableCommented:
As I am not seeing a specific server version for this question along with details I will suggest that you take a look at this answer from stackoverflow by Leandro López. It uses LDAP over AD to find disabled accounts.


class Program
{
    static void Main(string[] args)
    {
        const string ldap = "LDAP://your-ldap-server-here";

        using (DirectoryEntry conn = new DirectoryEntry(ldap))
        {
            using (DirectorySearcher searcher = new DirectorySearcher(conn))
            {
                searcher.Filter = "(|(samAccountName=userA)(samAccountName=userB))";
                searcher.PropertiesToLoad.Add("samAccountName");
                searcher.PropertiesToLoad.Add("userAccountControl");

                using (SearchResultCollection results = searcher.FindAll())
                {
                    foreach (SearchResult result in results)
                    {
                        int userAccountControl = Convert.ToInt32(result.Properties["userAccountControl"][0]);
                        string samAccountName = Convert.ToString(result.Properties["samAccountName"][0]);
                        bool disabled = ((userAccountControl & 2) > 0);

                        Console.WriteLine("{0} ({1:x}) :: {2}", samAccountName, userAccountControl, disabled);
                    }
                }
            }
        }

        Console.ReadLine();
    }
}

Open in new window

Leandro López:The second bit of userAccountControl will be 1 if the account is disabled.

All that really needs to be done is add a count variable and add to it for ever variable found in the foreach loop.

Besides, In your code above. Why would you be using a foreach to loop through a principle and not use the principle already defined to store the variable for each iteration of the loop and then display that instead??? That would explain why you get a 0 everytime as you would be referencing a non changing variable unlike the principle 'p' that is defined to hold the interated values for the loop. hope that helps.

UserPrincipal u  = new UserPrincipal(ctx);
PrincipalSearcher s = new PrincipalSearcher();
s.QueryFilter = u;
foreach(Principal p in u.FindAll())
{
  if(p.Enabled == false)// p instead of u
  count++;
}

Open in new window


0
Creating Active Directory Users from a Text File

If your organization has a need to mass-create AD user accounts, watch this video to see how its done without the need for scripting or other unnecessary complexities.

 
Russell_VenableCommented:
Also taking notes from Joe Kaplan.

You can also add

UserPrincipal u  = new UserPrincipal(ctx);
PrincipalSearcher s = new PrincipalSearcher(u);
s.QueryFilter = u;
PrincipalSearchResult<Principal> results = s.FindAll();
    if (results != null && results.Count() > 0)
    {
        foreach(Principal p in results)
        {
            if(p.Enabled == false)// p instead of u
               count++;
        }
    }
0
 
Russell_VenableCommented:
Thinking about that again you might want to replace s.FindAll() with FindOne() as your setting the Filter Object for one person. I would just make a array filled with a seperate principle searcher that is filled by FindAll() and make a method with the above code and use it recursive until it reaches the end of the array.
0
 
centemAuthor Commented:
Why p instead of u? Principal class does not have a "Enabled" property.
0
 
centemAuthor Commented:
BTW,
I'm running visual studio express 2010 on server 2003 SP 2.
0
 
Russell_VenableCommented:
I do believe I overlooked that part. I did a quick rewrite of it using VS2010 Pro.
using System;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;

namespace DisabledADAccounts
{
    class Program
    {
        static void Main(string[] args)
        {

            int count = 0;
            // Set search context.
            PrincipalContext ctx = new PrincipalContext(
                                      ContextType.ApplicationDirectory,
                                      "Host.Server.com:5000",
                                      "DC=SomeApp,DC=Server,DC=com",
                                      "Admin", "SecretPwd123");
            // Set filter to search for disabled accounts.
            UserPrincipal user = new UserPrincipal(ctx);
            // Check for disabled accounts set.
            user.Enabled = false;
            // Set name to search for. No error checking added here.
            user.Name = args[0]; // "user*"
            // Query for specific user. Asterisks are allowed.
            PrincipalSearcher s = new PrincipalSearcher(user);
            s.QueryFilter = user;
            PrincipalSearchResult<Principal> results = s.FindAll();
            Console.WriteLine("Disabled accounts starting with a name of [{0}]:", user.Name);

            // Go through PrincipleSearchResult array and store in principle variable for display.
            foreach (Principal result in results)
            {
                // Display disabled account name.
                Console.WriteLine("name: {0}", result.Name);
                count++;
            }
            Console.WriteLine("[*] # of Accounts Disabled searching for [{0}]: {1}", user.Name, count);
        }
    }
}

Open in new window



The problem with your code was it was returning the boolean number as result. If you put false it puts 1 if you put true it gives a 0. So having said that it will always give that number. Also the foreach loop was useless given that you did not utilize the stored variable (Principle) "p" instead you used (UserPrincipal) "u" which ignores the loop completely.  That is what I meant. The above code should work just like you want it too.

0

Featured Post

Veeam and MySQL: How to Perform Backup & Recovery

MySQL and the MariaDB variant are among the most used databases in Linux environments, and many critical applications support their data on them. Watch this recorded webinar to find out how Veeam Backup & Replication allows you to get consistent backups of MySQL databases.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now