枚举Windows用户组成员在远程系统使用c#
-
09-06-2019 - |
题
在c#,我需要能够
- 连接到一个远程系统,指定用户名/密码
- 名单成员本地系统上
- 获取的结果反馈到执行的计算机
例如,我会连接\SOMESYSTEM有适当的信任状,并取回一个列表中的当地管理员,包括SOMESYSTEM\管理员,SOMESYSTEM\鲍勃域\AlanH、"域\域管理员".
我已经尝试了这种有系统。directoryservices.accountmanagement但我遇到的问题与认证。有时候我会得到:
多个连接到一个服务器或者共享资源的相同的用户使用多于一个用户名是不允许的。断开以前的所有连接服务器或共享资源和后再试一次。(异常从HRESULT:0x800704C3)
上述的尝试,因为将有情况我无法简单地取消现有的驱动或UNC连接。
其他时候我的节目获得未知的误差和安全登录的远程系统的报告错误675,码0x19其是KDC_ERR_PREAUTH_REQUIRED.
我需要一个更简单和更易于发生错误的方式做到这一点!
解决方案
这应该是很容易做到,使用WMI。在这里,你有一个指向一些文档:
甚至如果你有没有先前经验与此它应该是很容易把那VB脚本代码在页底部的入一些。净码。
希望这有助于!
其他提示
davidg是在正确的轨道,我是计入他的回答。
但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("1","管理员","名为myusername","mypassword");我得到一个单一串返回:
1\管理员
程序\域管理员
实际WMI返回是更多这样的:
\\1\根\cimv2:Win32_UserAccount.Domain="1",Name="管理员"
...所以你可以看到,我不得不做一个小小的字符串中使漂亮起来。
我会推荐使用Win32API功能 NetLocalGroupGetMembers.它是更加直接的,比试图搞清楚这疯狂的LDAP法,这是必要的,对于一些其他的解决方案建议在这里。只要你冒充的用户运行检查,因为通过调用"修改",你应该不会遇到任何安全问题。
你可以找到的样本编码做的模拟 在这里,.
如果你需要帮助弄清如何调"NetLocalGroupGetMembers"从C#我建议你结账的杰瑞德牧师的PInvoke助理,这你可以 下载 从更.
如果你正在运行的代码中ASP.NET 程序在运行中IIS,并希望模拟用户访问该网站,以便使的呼吁,那么你可能需要授予"受信任的代表团"的权限的生产网络服务器。
如果你是上运行的桌面上,然后使用的活动的用户的安全凭证的应该不是个问题。
这可能是你的网络管理员有可能撤销访问的"安全对象"的特别机你都在试图访问。不幸的是,访问是有必要对所有的 网络管理api 功能的工作。如果是这种情况下,然后你会需要授予访问权限的"安全对象"不管什么用户要执行。与默认的窗户的安全设置的所有验证用户应有的访问,但是。
我希望这有所帮助。
-斯科特
你应该能够这样做的系统。DirectoryServices.DirectoryEntry.如果你有麻烦运行远程,也许你可以安装在远程机器来给你数据通过某种形式的RPC,如远程处理或网服务。但我想什么你要尝试,应尽可能远没有得到太花哨。
如果窗不会让你接通过它的登录机制,我认为你的唯一选项是执行远程机器上有一个开放的港口(无论是直接的或通过远程处理或一个网络服务,如所提到的).