在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。
我需要一种更简单且不易出错的方法来做到这一点!
答案 0 :(得分:2)
davidg走在正确的轨道上,我正在给他答案。
但是必要的WMI查询比直接更少,因为我不仅需要整个机器的用户列表,而且需要用户和组的子集,无论是本地还是域,是本地Administrators组的成员。为了记录,该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 \管理员
MYDOMAIN \ Domain Admins
实际的WMI回报更像是这样:
\\ SERVER1 \根\ CIMV2:Win32_UserAccount.Domain = “SERVER1”,名称= “管理员”
...所以你可以看到,我不得不做一些小的字符串操作来完善它。
答案 1 :(得分:1)
使用WMI应该很容易。这里有一个指向某些文档的指针:
WMI Documentation for Win32_UserAccount
即使您以前没有WMI经验,也应该很容易将页面底部的VB Script代码转换为某些.NET代码。
希望这有帮助!
答案 2 :(得分:1)
我建议使用Win32 API函数NetLocalGroupGetMembers。它比试图找出疯狂的LDAP语法要简单得多,这对于这里推荐的其他一些解决方案来说是必要的。只要您通过调用“LoginUser”来模拟要运行检查的用户,就不应该遇到任何安全问题。
您可以找到进行模拟的示例代码here。
如果你需要帮助搞清楚如何从C#调用“NetLocalGroupGetMembers”,我建议你查看Jared Parson的PInvoke助手,你可以从codeplex download。
如果您在IIS中运行的ASP.NET应用程序中运行代码,并且想要模拟访问网站以进行调用的用户,那么您可能需要向生产授予“Trusted for Delegation”权限网络服务器。
如果您在桌面上运行,那么使用活动用户的安全凭证应该不是问题。
网络管理员可能已撤消对您尝试访问的特定计算机的“安全对象”的访问权限。不幸的是,所有network management api函数都需要访问才能工作。如果是这种情况,那么您将需要为要执行的任何用户授予对“安全对象”的访问权限。但是,使用默认的Windows安全设置,所有经过身份验证的用户都应具有访问权限。
我希望这会有所帮助。
-Scott
答案 3 :(得分:0)
您应该可以使用System.DirectoryServices.DirectoryEntry执行此操作。如果您无法远程运行它,也许您可以在远程计算机上安装一些东西,通过某种RPC(如远程处理或Web服务)为您提供数据。但我认为你所尝试的应该可以远程进行而不会过于花哨。
答案 4 :(得分:0)
如果Windows不允许您通过它的登录机制进行连接,我认为您唯一的选择是使用开放端口(直接或通过远程处理或Web服务,如上所述)在远程计算机上运行某些东西。