6

在 c# 中,我需要能够

  • 连接到远程系统,根据需要指定用户名/密码
  • 列出该系统上本地组的成员
  • 将结果取回执行计算机

例如,我将使用适当的凭据连接到 \SOMESYSTEM,并取回本地管理员列表,包括 SOMESYSTEM\Administrator、SOMESYSTEM\Bob、DOMAIN\AlanH、“DOMAIN\Domain Administrators”。

我已经用 system.directoryservices.accountmanagement 试过了,但遇到了身份验证问题。有时我会得到:

不允许同一用户使用多个用户名与服务器或共享资源建立多个连接。断开与服务器或共享资源的所有先前连接,然后重试。(来自 HRESULT 的异常:0x800704C3)

以上正在尝试,因为在某些情况下我根本无法取消映射现有驱动器或 UNC 连接。

其他时候,我的程序收到 UNKNOWN ERROR,远程系统上的安全日志报告错误 675,代码 0x19,即 KDC_ERR_PREAUTH_REQUIRED。

我需要一种更简单且不易出错的方法来做到这一点!

4

5 回答 5

2

大卫走在了正确的轨道上,我相信他的答案。

但是所需的 WMI 查询并不那么简单,因为我不仅需要整个机器的用户列表,还需要本地管理员组成员的用户和组子集,无论是本地的还是域的。作为记录,该 WMI 查询是:

SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = "Win32_Group.Domain='thehostname',Name='thegroupname'"

这是完整的代码片段:

public string GroupMembers(string targethost, string groupname, string targetusername, string targetpassword)
        {
            StringBuilder result = new StringBuilder(); 
            try
            {
                ConnectionOptions Conn = new ConnectionOptions();
                if (targethost != Environment.MachineName) //WMI errors if creds given for localhost
                {
                    Conn.Username = targetusername; //can be null
                    Conn.Password = targetpassword; //can be null
                }
                Conn.Timeout = TimeSpan.FromSeconds(2);
                ManagementScope scope = new ManagementScope("\\\\" + targethost + "\\root\\cimv2", Conn);
                scope.Connect();
                StringBuilder qs = new StringBuilder();
                qs.Append("SELECT PartComponent FROM Win32_GroupUser WHERE GroupComponent = \"Win32_Group.Domain='");
                qs.Append(targethost);
                qs.Append("',Name='");
                qs.Append(groupname);
                qs.AppendLine("'\"");
                ObjectQuery query = new ObjectQuery(qs.ToString());
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
                ManagementObjectCollection queryCollection = searcher.Get();
                foreach (ManagementObject m in queryCollection)
                {
                    ManagementPath path = new ManagementPath(m["PartComponent"].ToString());                                        
                    { 
                        String[] names = path.RelativePath.Split(',');
                        result.Append(names[0].Substring(names[0].IndexOf("=") + 1).Replace("\"", " ").Trim() + "\\"); 
                        result.AppendLine(names[1].Substring(names[1].IndexOf("=") + 1).Replace("\"", " ").Trim());                    
                    }
                }
                return result.ToString();
            }
            catch (Exception e)
            {
                Console.WriteLine("Error. Message: " + e.Message);
                return "fail";
            }
        }

所以,如果我调用 Groupmembers("Server1", "Administrators", "myusername", "mypassword"); 我得到一个返回的字符串:

SERVER1\Administrator
MYDOMAIN\域管理员

实际的 WMI 返回更像这样:

\\SERVER1\root\cimv2:Win32_UserAccount.Domain="SERVER1",Name="Administrator"

...所以你可以看到,我不得不做一些字符串操作来美化它。

于 2008-08-23T08:14:15.430 回答
1

使用 WMI 应该很容易做到这一点。在这里,您有一些文档的指针:

Win32_UserAccount 的 WMI 文档

即使您以前没有使用 WMI 的经验,也应该很容易将页面底部的 VB 脚本代码转换为一些 .NET 代码。

希望这有帮助!

于 2008-08-22T00:57:21.463 回答
1

我建议使用 Win32 API 函数NetLocalGroupGetMembers。这比试图找出疯狂的 LDAP 语法要简单得多,这对于此处推荐的其他一些解决方案是必需的。只要您通过调用“LoginUser”来模拟要运行检查的用户,就不会遇到任何安全问题。

您可以在此处找到进行模拟的示例代码。

如果您需要帮助了解如何从 C# 调用“NetLocalGroupGetMembers”,我建议您查看 Jared Parson 的 PInvoke 助手,您可以从 codeplex下载该助手。

如果您在 IIS 中运行的 ASP.NET 应用程序中运行代码,并且想要模拟访问网站的用户以进行调用,那么您可能需要向生产 Web 服务器授予“委托授权”权限。

如果您在桌面上运行,那么使用活动用户的安全凭据应该不是问题。

您的网络管理员可能已经撤销了对您尝试访问的特定机器的“安全对象”的访问权限。不幸的是,所有网络管理 API功能都需要访问权限才能正常工作。如果是这种情况,那么您将需要为您想要执行的任何用户授予对“安全对象”的访问权限。但是,使用默认的 Windows 安全设置,所有经过身份验证的用户都应该具有访问权限。

我希望这有帮助。

-斯科特

于 2008-08-22T01:36:33.757 回答
0

您应该可以使用 System.DirectoryServices.DirectoryEntry 执行此操作。如果您在远程运行它时遇到问题,也许您可​​以在远程机器上安装一些东西,以便通过某种 RPC 向您提供数据,例如远程处理或 Web 服务。但是我认为您正在尝试的东西应该可以远程进行,而不会太花哨。

于 2008-08-22T00:43:13.823 回答
0

如果 Windows 不允许您通过其登录机制进行连接,我认为您唯一的选择是在具有开放端口的远程计算机上运行某些东西(如前所述,直接或通过远程处理或 Web 服务)。

于 2008-08-22T00:55:35.557 回答