Enumerating Users using WMI.NET and C#

14 10 2007

Recently, I had to get all the user names in my local machine. I was searching for a proper method and was really hard to get one. I knew I have to use WMI, but the biggest obstacle was of combining different WMI queries to get the result 🙂

The WMI classes that immediately came into my mind were,

Each of the classes have their own use. However, Win32_Account forms the main class and other classes derive Win32_Account

So, to get all User Accounts, you could just query,

“select * from Win32_UserAccount where Domain=’YOURDOMAIN'”

And to get all Groups, you could just query,

“select * from Win32_GroupUser where Domain=’YOURDOMAIN'”

So, using C#,

For User accounts,

public static void GetUsers()
{
            SelectQuery sQuery = new SelectQuery("Win32_UserAccount","Domain='CHAKS-PC'");

            try
            {
                ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);

                Console.WriteLine("User Accounts");
                Console.WriteLine("");

                foreach (ManagementObject mObject in mSearcher.Get())
                { 
                    Console.WriteLine(mObject["Name"]);              
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.ReadKey();
 }

And for Groups,

public static void GetGroups()
 {
            SelectQuery sQuery = new SelectQuery("Win32_Group", "Domain='CHAKS-PC'");

            try
            {
                ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);

                Console.WriteLine("Groups");
                Console.WriteLine("");

                foreach (ManagementObject mObject in mSearcher.Get())
                {
                    Console.WriteLine(mObject["Name"]);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.ReadKey();
 }

Now to get Users corresponding to a particular group, we need to query Win32_GroupUser and there comes the trick 😉

The Win32_GroupUser is an association class and relates a group and the account to which that is a member of that group.

So, now our query changes to,

“select * from Win32_GroupUser where GroupComponent='”‘Win32_Group.Domain=’domain-name’,Name=’group-name””‘”

And our C# code changes to,

public static void GetUsers(String DomainName, String GroupName)
{
            #region Build WMI query using SelectQuery
            ///<summary>
            /// Alternate method for building query
            /// Which I think is better approach
            ///</summary>
            StringBuilder sBuilder = new StringBuilder("GroupComponent=");
            sBuilder.Append('"');
            sBuilder.Append("Win32_Group.Domain=");
            sBuilder.Append("'");
            sBuilder.Append(DomainName);
            sBuilder.Append("'");
            sBuilder.Append(",Name=");
            sBuilder.Append("'");
            sBuilder.Append(GroupName);
            sBuilder.Append("'");            
            sBuilder.Append('"');
            SelectQuery sQuery = new SelectQuery("Win32_GroupUser", sBuilder.ToString());
            #endregion           

            ///<summary>
            /// Execute the query
            /// Construct a ManagementPath from the PartComponent and check for ClassName
            /// and extract the UserName
            /// Depending on which method you used to build the query,
            /// pass the String or SelectQuery object to ManagementObjectSearcher
            ///</summary>
            try
            {
                ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);

                foreach (ManagementObject mObject in mSearcher.Get())
                {
                    ManagementPath path = new ManagementPath(mObject["PartComponent"].ToString());

                    if (path.ClassName == "Win32_UserAccount")
                    {
                        String[] names = path.RelativePath.Split(',');
                        Console.WriteLine(names[1].Substring(names[1].IndexOf("=") + 1).Replace('"', ' ').Trim());
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }

            Console.ReadKey();
}

You can download the source code from here


Actions

Information

14 responses

10 01 2008
Irving Nam

If you wrote the query without specifying a domain, would you get all accounts in all domains? For example, if I wanted to get the list of all users in the Local Admin group and this group contained users from domain A and B, do you get these?

11 01 2008
Chaks

Hi Irving,

As far as I know, the API doesn’t have the intelligence to find all the domains in your network. You may have to write a separate wrapper and use foreach to loop through them and enumerate users in that particular domain.

16 01 2008
Frank Pikelner

What changes would the code require to obtain the listing of users/groups results in Unicode versus ANSI to support International characters?

25 01 2008
alex

Hello,

How can you add a user to a group (the administrators group) on a remote machine using WMI ? is this possible?

Thanks,
alex

26 01 2008
Chaks

Hi Alex, I have not dealt with separate machine, rather , its more to accounts in a Domain (Server Environment).

29 02 2008
Mark Gardner

There was a problem with Domain Local Groups being filtered incorrectly and the groups would not show up in this script. MS has a hotfix for that issue.

http://support.microsoft.com/kb/940527

15 05 2008
shashank

Further to Alex’s questions, do you have to WMI code to write to the local admin group?

would appreciate any help in that direction.

8 08 2008
maryam

hi
please tell me how to extract users and user groups from a file using wmi, instead of having to type them out to store the list. the code you have written is helpful but i’d really appreciate if you’d give me a few other laternatives of the same kind. btw the users use a domain i need that list for backup in case the server’s down.
thanks

13 08 2008
Harry

Great !!

10 01 2009
Suheb Ahmad

i need help to get change the domain name. is there any body knows how can it be changed in program. like c# or vb.net or any other language.

Thanks in advance

9 02 2011
Pavan Kumar

Hi Can any one tell me how to get the names and domains using WbemScripting

26 09 2012
Pawel Czopowik

Chaks, thanks so much for this code example. In particular, the last block of code, dealing with extracting users from a local group, was very helpful – I was having a tough time working through it until I found this post! Constructing the query itself was a pain, not to mention the rest :).

20 09 2013
best road bike bicycle tires

Thanks a lot for sharing this with all of us you actually
realize what you’re speaking about! Bookmarked.
Kindly additionally seek advice from my web site =). We may have a hyperlink exchange agreement among us

23 09 2013
nude women over 40

Hi to all, how is everything, I think every one
is getting more from this web page, and your views are good designed for new people.

Leave a comment