Подтвердить что ты не робот

Получить задание с помощью System.DirectoryServices.AccountManagement

Я успешно использовал код AccountManagement для извлечения базовой информации AD, но только возвращал очень ограниченный набор информации о возвращенном объекте. Как получить расширенную информацию из AD с помощью функции AccountManagement. В частности, название должности или название, которое, как представляется, вызывается в моем экземпляре AD.

Я знаю, как это сделать, используя старые DirectoryServices, но я хотел бы знать, как это сделать, используя новое пространство имен.

4b9b3361

Ответ 1

Да, набор свойств по умолчанию на 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 и его истории расширяемости:

Обновление: извините - вот класс UserPrincipalExSearchFilter - пропустил этот текст в исходном сообщении. Он просто показывает возможность также расширить фильтры поиска, если необходимо:

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

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

Ответ 2

Чтобы увеличить выше, я выбил метод расширения для вызова ExtensionGet. Он использует отражение, чтобы получить защищенный метод, который вам в противном случае пришлось бы наследовать. Возможно, вам придется использовать это, если вы возвращаете UserPrincipalObjects из Groups.Members, например

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;
    }
}

Ответ 3

Есть более простые способы добраться до этой информации. Вот как я добрался до должности в 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