如何查找计算机所属的组织单位?(Active Directory C#)

8
我想在C#中找到我电脑所属的最具体的组织单位。我有获取所需信息的代码,但感觉不够稳健,需要进行复杂的解析。有更好的替代方案吗?思路如何?任何帮助都将不胜感激!
实际上,我想要的是与命令提示符命令等效的内容:
dsquery computer -name COMP-HERE

但我需要用C#来实现,这证明是有问题的。

DirectorySearcher d = new DirectorySearcher("CN=COMP-HERE");
d.PropertiesToLoad.Add("adspath");
SearchResultCollection results = d.FindAll();
foreach (SearchResult searchResult in results) {
    foreach (string propertyKey in searchResult.Properties.PropertyNames) {
        ResultPropertyValueCollection valueCollection = searchResult.Properties[propertyKey];
        foreach (Object propertyValue in valueCollection) {
            Console.WriteLine(
            "{0}:{1}",
            propertyKey,
            propertyValue.ToString());
        }
    }
}
Console.ReadLine();
3个回答

4
这里有一个使用 System.DirectoryServices.AccountManagement 命名空间中的 PrincipalContextComputerPrincipal 的解决方案。
string machineOU;
using (var context = new PrincipalContext(ContextType.Domain))
using (var comp = ComputerPrincipal.FindByIdentity(context, Environment.MachineName))
{
    machineOU = String.Join(",", comp.DistinguishedName.Split(',')
                                                       .SkipWhile(s => !s.StartsWith("OU="))
                                                       .ToArray());
}

机器的专有名称(distinguished name)在Linq处理中被分割成其组成元素,跳过第一个OU=...元素之前的任何元素,然后重新组合其余部分,从而留下包含OU的专有名称。
更多信息: System.DirectoryServices.AccountManagement命名空间中的类提供了各种类型安全主体(账户)的相当高级抽象。 PrincipalContext基本上是帐户存储库的抽象。它可以引用机器的帐户数据库 (PrincipalType.Machine),Active Directory域或全局目录 (PrincipalType.Domain),或Active Directory应用程序分区 (PrincipalType.ApplicationDirectory)。 new PrincipalContext(ContextType.Domain)创建表示本地Active Directory域的PrincipalContext
一旦我们获得这个上下文,就可以使用各种主体类型(可以是UserPrincipalComputerPrincipalGroupPrincipal)上的FindBy...()静态方法来查找我们正在寻找的AD对象。

我的C#和Active Directory知识有限...你能详细说明一下这段代码到底在做什么吗?我对PrincipalContext有点困惑。不过代码运行得很好!我只是想理解它。 - user1507986
使用SkipWhile而不是Where的原因是什么? - Bob Vale
我不能再给你点赞了(实际上我根本无法给你点赞,因为我的声望不够),所以你只能接受我的感谢。你真棒,这是我在 Stack Exchange 上发布的第一个问题,非常积极的体验。 - user1507986
@BobVale - 在这种情况下,最终结果基本相同,但对于这种情况,“SkipWhile”更有效。 “Where”将对序列中的每个元素应用测试,而“SkipWhile”仅测试元素,直到找到一个未通过测试的元素,然后将序列的剩余元素直接传递到输出序列。 - Andrew Cooper
只是想要严格回答OU所问的问题,但您的答案包括了O元素和dc元素。 - Bob Vale
@BobVale - 这些元素是因为我正在返回OU的可分辨名称(完整的LDAP路径)。 - Andrew Cooper

0

这是对我有效的方法

IEnumerable<string> machineOU;
using (var context = new PrincipalContext(ContextType.Domain))
using (var comp = ComputerPrincipal.FindByIdentity(context, Environment.MachineName))
{
  machineOU = comp.DistinguishedName.Split(',').Where(s => s.StartsWith("OU="));
}

0

你发的第一个链接几乎与我要做的相反(尽管非常相关)。它试图找到OU,可能是为了找到其中的内容。而我正在尝试找到一个计算机所在的OU。感谢您的及时回复!这让我很意外。 - user1507986

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接