?
Solved

Count AD disabled accounts C#

Posted on 2011-03-14
8
Medium Priority
?
2,515 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 
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 2000 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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Always backup Domain, SYSVOL etc.using processes according to Microsoft Best Practices. This is meant as a disaster recovery process for small environments that did not implement backup processes and did not run a secondary domain controller that ne…
Compliance and data security require steps be taken to prevent unauthorized users from copying data.  Here's one method to prevent data theft via USB drives (and writable optical media).
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…
Suggested Courses

777 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