Tuesday, October 14, 2008

Getting User/Group details in Windows

In one of the applications that I worked on recently, I had to determine whether the given username (loaded from XML) is actually a local username. First I felt its bit tricky. But instinct told me to look into WMI and I got the solution quickly.

The idea is to use ManagementObjectSearcher objects for searching the required WMI class. For a list of local users, we need to search for Win32_UserAccount. Win32_Group represents groups defined in the local system.

First, we need to add a reference to the System.Management component. Code snippets given below shows how to get the user & group listing:

using System.Management;

public string[] GetUsers(string machineName)
{
    return GetItems("Win32_UserAccount", machineName);
}

public string[] GetGroups(string machineName)
{
    return GetItems("Win32_Group", machineName);
}

private string[] GetItems(string className, string machineName)
{
    string[] items = null;

    try
    {
        // Prepare the select query
        SelectQuery query = new SelectQuery(className,
            string.Format("Domain='{0}'", machineName));

        using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
        {
            StringBuilder builder = new StringBuilder();

            foreach (ManagementObject mgmtObject in searcher.Get())
            {
                if (builder.Length != 0)
                    builder.Append('\t');

                builder.Append(mgmtObject["Name"]);
            }

            // Get the array
            items = builder.ToString().Split('\t');
        }
    }
    catch
    {
        throw;
    }

    return items;
}

The actual processing is done by GetItems(). Machine name can be obtained by using the System.Environment.MachineName property.

Now we can extend this to get all users in a specific group. The Win32_GroupUser class can be used for obtaining this information. If the computer is in a workgroup, we can pass the computer name (Environment.MachineName) to domainName parameter.

public string[] GetUsersInGroup(string domainName, string groupName)
{
    string[] users = null;

    try
    {
        string queryString = string.Format("GroupComponent=\"Win32_Group.Domain=\'{0}\',Name=\'{1}'\"",
                                                        domainName,
                                                        groupName);

        // Prepare the select query
        SelectQuery query = new SelectQuery("Win32_GroupUser", queryString);

        using (ManagementObjectSearcher objectSearcher = new ManagementObjectSearcher(query))
        {
            StringBuilder builder = new StringBuilder();

            foreach (ManagementObject mObject in objectSearcher.Get())
            {
                ManagementPath path = new ManagementPath(mObject["PartComponent"].ToString());
                if (path.ClassName == "Win32_UserAccount")
                {
                    // Split the path (2 parts)
                    string[] names = path.RelativePath.Split(',');

                    if (builder.Length != 0)
                        builder.Append('\t');

                    // Extract the 'Name' part
                    builder.Append(names[1].Substring(names[1].IndexOf("=") + 1).Replace('"', ' ').Trim());
                }
            }

            // Get the array
            users = builder.ToString().Split('\t');
        }
    }
    catch
    {
        throw;
    }

    return users;
}

If you face any issue - like getting incorrect data - have a look at the below link for troubleshooting tips.

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

1 comment:

cengiz said...

Thank you very much. Cengiz