Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all user account names in XP, Vist & 7, for 32 or 64 bit, and any OS language

Tags:

c#

.net

winforms

I have a C# winform application that will be installed on Windows 7, Vista and XP machines, either 32 or 64 bit, with operating systems in English, German and Spanish (and other languages in the future).

I need to get a list of all admin and user account names on the local machine. I just need a list of the account names, nothing more.

The problem is my code works only for English language operating systems.

Is there a way to get the user names on a local machine regardless of language of the OS, and regardless of whether it is XP, Vista or 7, and regardless of whether it is 32 or 64 bit?

I read a post somewhere about using the SID to get the local admin name in case it has been renamed. Can using the SID be helpful in solving my problem?

Below is my code. On a German language OS computer, the code fails on the line "DirectoryEntry admGroup = localMachine.Children.Find("administrators", "group");". It fails here most likely because in the German OS the words "administrators", "group" are likely spelled differently. The same also is likely true for Spanish language OS.

My code for 32 bit OS:

DirectoryEntry localMachine = new DirectoryEntry(
    "WinNT://" + Environment.MachineName);

DirectoryEntry admGroup = localMachine.Children.
    Find("administrators", "group");
object adminmembers = admGroup.Invoke("members", null);

DirectoryEntry userGroup = localMachine.Children.Find("users", "group");
object usermembers = userGroup.Invoke("members", null);

//Retrieve each user name.
foreach (object groupMember in (IEnumerable)adminmembers)
{
    DirectoryEntry member = new DirectoryEntry(groupMember);
    if (!(member.Name == "admin" || member.Name == "Domain Admins"))
    {
          drow = dtWindowsUser.NewRow();
          drow["WindowsUser"] = member.Name;

          //Add row to datatable
          dtWindowsUser.Rows.Add(drow);
    }
}
foreach (object groupMember in (IEnumerable)usermembers)
{
    DirectoryEntry member = new DirectoryEntry(groupMember);
    if (!(member.Name == "ACTUser" || member.Name == "ASPNET" || 
          member.Name == "Domain Users" || 
          member.Name == "Authenticated Users" || 
          member.Name == "INTERACTIVE" || 
          member.Name == "SQLDebugger"))
    {
        drow = dtWindowsUser.NewRow();
        drow["WindowsUser"] = member.Name;

        //Add row to datatable
        dtWindowsUser.Rows.Add(drow);
    }
}

My code for 64 bit OS:

SelectQuery query = new SelectQuery("Win32_UserAccount");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject envVar in searcher.Get())
{
    str_name = envVar["Name"].ToString();

    if (!(str_name == "admin" || str_name == "Domain Admins"))  
    {
        if (!(str_name == "ACTUser" || 
              str_name == "ASPNET" || 
              str_name == "Domain Users" || 
              str_name == "Authenticated Users" || 
              str_name == "INTERACTIVE" || 
              str_name == "SQLDebugger"))
        {
            if (!(str_name == "HomeGroupUser$"))
            {
                drow = dtWindowsUser.NewRow();
                drow["WindowsUser"] = str_name;

                //Add row to datatable
                dtWindowsUser.Rows.Add(drow);
            }
        }
    }
}
like image 632
Frederick Avatar asked Jun 11 '11 21:06

Frederick


People also ask

How do I view all users in Windows XP?

Choose Start→Control Panel→Administrative Tools→Computer Management. Click the Local Users and Groups icon in the left pane of the window.

How do I get a list of users in Windows?

To view user accounts on your computer: Open an elevated/administrator command prompt. Type net user and press Enter. Observe the list of user accounts on your computer.


1 Answers

Even on a system using English, you don't want to retrieve groups by name - they could be renamed from what you expect. For built in groups like Administrators you want to use a well known SID which will work no matter what language is used to name the group.

This is one way to retrieve the data you want...

SecurityIdentifier builtinAdminSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);

PrincipalContext ctx = new PrincipalContext(ContextType.Machine);

GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, builtinAdminsSid.Value);

foreach (Principal p in group.Members)
{
    Console.WriteLine(p.Name);
}


Edit: @jyoung's suggestion of using WellKnownSidType is a much better idea than using a hard coded magic value like String builtinAdminsSidString = "S-1-5-32-544"; so I changed the example code above.

like image 55
Frank Boyne Avatar answered Oct 18 '22 19:10

Frank Boyne