Solved

Count AD disabled accounts C#

Posted on 2011-03-14
8
2,222 Views
Last Modified: 2012-05-11
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
Comment
Question by:centem
  • 4
  • 3
8 Comments
 
LVL 51

Expert Comment

by:Netman66
ID: 35139654
Did you try u.Disabled == True?
0
 

Author Comment

by:centem
ID: 35141458
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
 
LVL 15

Expert Comment

by:Russell_Venable
ID: 35144905
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
 
LVL 15

Expert Comment

by:Russell_Venable
ID: 35144939
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
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 15

Expert Comment

by:Russell_Venable
ID: 35144971
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
 

Author Comment

by:centem
ID: 35155130
Why p instead of u? Principal class does not have a "Enabled" property.
0
 

Author Comment

by:centem
ID: 35155181
BTW,
I'm running visual studio express 2010 on server 2003 SP 2.
0
 
LVL 15

Accepted Solution

by:
Russell_Venable earned 500 total points
ID: 35158679
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

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Companies that have implemented Microsoft’s Active Directory need to ensure that the Active Directory is configured and operating properly. If there are issues found and not resolved, it eventually leads the components to fail or stop working and fi…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
This tutorial will walk an individual through the process of transferring the five major, necessary Active Directory Roles, commonly referred to as the FSMO roles to another domain controller. Log onto the new domain controller with a user account t…
This tutorial will walk an individual through the process of configuring their Windows Server 2012 domain controller to synchronize its time with a trusted, external resource. Use Google, Bing, or other preferred search engine to locate trusted NTP …

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now