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
Solved

Count AD disabled accounts C#

Posted on 2011-03-14
8
2,348 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
VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

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

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

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

While rebooting windows server 2003 server , it's showing "active directory rebuilding indices please wait" at startup. It took a little while for this process to complete and once we logged on not all the services were started so another reboot is …
The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
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 from a Windows Server 2008 domain controller to a Windows Server 2012 domain controlle…
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…

840 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