Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 使用System.DirectoryServices.AccountManagement获取职务_C# 4.0_Active Directory - Fatal编程技术网

C# 4.0 使用System.DirectoryServices.AccountManagement获取职务

C# 4.0 使用System.DirectoryServices.AccountManagement获取职务,c#-4.0,active-directory,C# 4.0,Active Directory,我已经成功地使用AccountManagement代码检索了基本的广告信息,但是它只返回了一组非常有限的关于返回对象的信息。如何使用AccountManagement功能从AD获取扩展信息。具体地说,就是我在广告中所说的职位或头衔 我知道如何使用旧的DirectoryServices,但我想知道如何使用新的名称空间。是的,UserPrincipal上的默认属性集非常有限,但最重要的是:有一个整洁的可扩展性故事 您需要从UserPrincipal定义一个降序类,然后如果需要,您可以非常轻松地访问更

我已经成功地使用AccountManagement代码检索了基本的广告信息,但是它只返回了一组非常有限的关于返回对象的信息。如何使用AccountManagement功能从AD获取扩展信息。具体地说,就是我在广告中所说的职位或头衔


我知道如何使用旧的DirectoryServices,但我想知道如何使用新的名称空间。

是的,
UserPrincipal
上的默认属性集非常有限,但最重要的是:有一个整洁的可扩展性故事

您需要从
UserPrincipal
定义一个降序类,然后如果需要,您可以非常轻松地访问更多属性

骨架看起来像这样:

namespace ADExtended
{
    [DirectoryRdnPrefix("CN")]
    [DirectoryObjectClass("User")]
    public class UserPrincipalEx : UserPrincipal
    {
        // Inplement the constructor using the base class constructor. 
        public UserPrincipalEx(PrincipalContext context) : base(context)
        { }

        // Implement the constructor with initialization parameters.    
        public UserPrincipalEx(PrincipalContext context,
                             string samAccountName,
                             string password,
                             bool enabled) : base(context, samAccountName, password, enabled)
        {} 

        UserPrincipalExSearchFilter searchFilter;

        new public UserPrincipalExSearchFilter AdvancedSearchFilter
        {
            get
            {
                if (null == searchFilter)
                    searchFilter = new UserPrincipalExSearchFilter(this);

                return searchFilter;
            }
        }

        // Create the "Title" property.    
        [DirectoryProperty("title")]
        public string Title
        {
            get
            {
                if (ExtensionGet("title").Length != 1)
                    return string.Empty;

                return (string)ExtensionGet("title")[0];
            }
            set { ExtensionSet("title", value); }
        }

        // Implement the overloaded search method FindByIdentity.
        public static new UserPrincipalEx FindByIdentity(PrincipalContext context, string identityValue)
        {
            return (UserPrincipalEx)FindByIdentityWithType(context, typeof(UserPrincipalEx), identityValue);
        }

        // Implement the overloaded search method FindByIdentity. 
        public static new UserPrincipalEx FindByIdentity(PrincipalContext context, IdentityType identityType, string identityValue)
        {
            return (UserPrincipalEx)FindByIdentityWithType(context, typeof(UserPrincipalEx), identityType, identityValue);
        }
    }
}
这几乎就是全部!
ExtensionGet
ExtensionSet
方法允许您“深入”底层目录条目,并获取您可能感兴趣的所有属性

现在,在代码中,使用新的
UserPrincipalEx
类而不是
UserPrincipal

using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
    // Search the directory for the new object. 
    UserPrincipalEx myUser = UserPrincipalEx.FindByIdentity(ctx, "someUserName");

    if(myUser != null)
    { 
        // get the title which is now available on your "myUser" object!
        string title = myUser.Title;
    }
}
阅读有关
System.DirectoryServices.AccountManagement
命名空间及其可扩展性故事的所有内容:

更新:对不起-这是
userprincipalexearchfilter
类-在原始帖子中错过了该类。它只是显示了扩展搜索过滤器的能力,如果需要:

public class UserPrincipalExSearchFilter : AdvancedFilters
{
    public UserPrincipalExSearchFilter(Principal p) : base(p) { }

    public void LogonCount(int value, MatchType mt)
    {
        this.AdvancedFilterSet("LogonCount", value, typeof(int), mt);
    }
}

为了增强上述功能,我设计了一个扩展方法来调用ExtensionGet。它使用反射来获取您必须继承的受保护方法。如果要从组返回UserPrincipalObject,则可能需要使用此选项

public static class AccountManagmentExtensions
{
    public static string ExtensionGet(this UserPrincipal up, string key)
    {
        string value = null;
        MethodInfo mi = up.GetType()
            .GetMethod("ExtensionGet", BindingFlags.NonPublic | BindingFlags.Instance);

        Func<UserPrincipal, string, object[]> extensionGet = (k,v) => 
            ((object[])mi.Invoke(k, new object[] { v }));

        if (extensionGet(up,key).Length > 0)
        {
            value = (string)extensionGet(up, key)[0]; 
        }

        return value;
    }
}
公共静态类AccountManagementExtensions
{
公共静态字符串扩展集(此UserPrincipal up,字符串键)
{
字符串值=null;
MethodInfo mi=up.GetType()
.GetMethod(“ExtensionGet”,BindingFlags.NonPublic | BindingFlags.Instance);
Func extensionGet=(k,v)=>
((对象[])mi.Invoke(k,新对象[]{v}));
if(扩展网(向上,键)。长度>0)
{
value=(字符串)extensionGet(向上,键)[0];
}
返回值;
}
}

有更简单的方法获取这些信息。以下是我在VB.NET中获得职务的方法:

Dim yourDomain As New PrincipalContext(ContextType.Domain, "yourcompany.local")
Dim user1 As UserPrincipal = UserPrincipal.FindByIdentity(yourDomain, principal.Identity.Name)
Dim Entry As DirectoryServices.DirectoryEntry = user1.GetUnderlyingObject()

Dim JobTitle As String = Entry.Properties.Item("Title").Value.ToString

为了扩展Programmierus的评论,这里有一个在C#中动态执行此操作的简单方法


这种类型(UserPrincipalExearchFilter)来自哪里?我是否需要使用上面的模式创建此类型?实际上,我把那几行代码拉了出来,它似乎工作得很好(除非我遗漏了什么)。@Jay:对不起,我的错-忘了包括这个。更新了我的回复。@marc\s。感谢您指出了可扩展性点(ExtensionGet/Set保护的方法),我想有时候更靠近家是值得的!!)无论如何,您是否知道使用派生的prinicpal对象所需的安全问题/config。我已经实现了上面的子类,并得到一个异常,读取“UserPrincpalEx类型的主体对象不能用于查询此存储”。有什么想法吗?谢谢,对不起。我已经完成了代码,但不知怎么地删除了顶部的属性。如果没有这种装饰,身份就会动摇。Thanks@Force--在我将
DirectoryObjectClass
从“Person”更改为“User”之前,我一直都遇到同样的错误。(希望你在一年前就知道了)+1这是一个非常方便的技巧。我说的是“哦,现在我需要子类!”你只是在说这个方法是受保护的,设计成可以通过子类访问。让我想起了我写的一个主题,关于如何使用.NET反射来“破坏”OOP概念:键的值不是字符串值。类似于
System.\u comObject
accountExpires
property.Works中。必须引用System.DirectoryServices。C#方式:
(ldapEntry.getunderyingobject()作为DirectoryEntry)?.Properties[“Title”]。Value??“空”
    public static string GetProperty(UserPrincipal userPrincipal, string property)
    {
        DirectoryEntry d = (DirectoryEntry)userPrincipal.GetUnderlyingObject();
        return d.Properties[property]?.Value?.ToString();
    }