【问题标题】:How to get all user account names in XP, Vist & 7, for 32 or 64 bit, and any OS language如何在 XP、Vista 和 7 中获取 32 位或 64 位以及任何操作系统语言的所有用户帐户名称
【发布时间】:2011-06-11 21:18:44
【问题描述】:

我有一个 C# winform 应用程序,它将安装在 32 位或 64 位的 Windows 7、Vista 和 XP 机器上,操作系统支持英语、德语和西班牙语(以及未来的其他语言)。

我需要获取本地计算机上所有管理员和用户帐户名称的列表。我只需要一个帐户名称列表,仅此而已。

问题是我的代码仅适用于英语操作系统。

有没有办法在本地机器上获取用户名,无论操作系统的语言如何,无论是 XP、Vista 还是 7,无论是 32 位还是 64 位?

我在某处阅读了一篇关于使用 SID 获取本地管理员名称的帖子,以防它被重命名。使用 SID 可以帮助解决我的问题吗?

下面是我的代码。在德语操作系统计算机上,代码在“DirectoryEntry admGroup = localMachine.Children.Find("administrators", "group");" 行上失败。它很可能在这里失败,因为在德语操作系统中,“管理员”、“组”这两个词的拼写可能不同。西班牙语操作系统可能也是如此。

我的 32 位操作系统代码:

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);
    }
}

我的 64 位操作系统代码:

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);
            }
        }
    }
}

【问题讨论】:

  • 为什么 32 位和 64 位系统的代码不同?
  • @svick - 64 位 Windows 7 的代码失败,所以我添加了额外的代码。它在德语 XP 失败的同一行上失败了。

标签: c# .net winforms


【解决方案1】:

即使在使用英语的系统上,您也不希望按名称检索组 - 它们可以按照您的期望重命名。对于像管理员这样的内置组,您希望使用well known SID,无论使用哪种语言命名组,它都可以使用。

这是检索所需数据的一种方法...

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);
}


编辑:@jyoung 建议使用 WellKnownSidType 比使用像 String builtinAdminsSidString = "S-1-5-32-544"; 这样的硬编码魔法值要好得多,所以我更改了上面的示例代码。

【讨论】:

  • 谢谢!您和 jyoung 一起为我提供了重做代码所需的信息。我使用了与“UserPrincipal user = new UserPrincipal(ctx);”一起提供的内容代码的 sn-p。
【解决方案2】:

这个如何获取内置管理员名称的示例可能会有所帮助。

var builtinAdministratorsName = new SecurityIdentifier(
    WellKnownSidType.BuiltinAdministratorsSid, null).
    Translate(typeof(NTAccount)).Value;

【讨论】:

  • 谢谢!从你的代码和弗兰克的代码中,我能够重做我的代码以获得我需要的东西。
【解决方案3】:

请试试这个:

using System.Management;

using (var accountSearcher = new System.Management.ManagementObjectSearcher("SELECT * FROM Win32_UserAccount WHERE LocalAccount=True"))
    using (var accountCollection = accountSearcher.Get())
        foreach (var account in accountCollection)
            this.listBox1.Items.Add(account["Name"].ToString());

【讨论】:

    【解决方案4】:

    使用GetSystemUILanguage 获取语言,然后使用switch case(你必须自己搜索文件夹名称)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-07
      • 1970-01-01
      • 2012-09-01
      • 2013-08-29
      • 2011-02-20
      • 2015-09-26
      • 2012-09-11
      • 1970-01-01
      相关资源
      最近更新 更多