2012-03-02 55 views
18

我已成功使用AccountManagement代碼檢索基本的AD信息,但它僅返回關於返回對象的非常有限的一組信息。我如何使用AccountManagement功能從AD獲得擴展信息。具體來說,就像我在AD的實例中似乎要調用的職位或職位。使用System.DirectoryServices.AccountManagement獲取職位名稱

我知道如何使用舊的DirectoryServices來做到這一點,但我想知道如何使用新的名稱空間來做到這一點。

回答

32

是的,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); 
     } 
    } 
} 

這就是真的,幾乎所有有!該ExtensionGetExtensionSet方法讓你「到達下」進入基本目錄條目,並抓住了所有的屬性,你可能會感興趣....

現在,在你的代碼,使用新的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); 
    } 
} 
+0

哪裏該類型(UserPrincipalExSearchFilter)從何而來?我是否需要使用上述模式創建此類型?實際上,我將這幾行代碼拉出來,它看起來很完美(除非我錯過了某些東西)。 – Jay 2012-03-04 23:44:37

+0

@Jay:對不起 - 我的不好 - 忘了包括這個。更新了我的回覆。 – 2012-03-05 05:51:54

+0

@ marc_s。 Thankyou指出的可擴展性點(ExtensionGet/Set受保護的方法),我想它有時看起來更接近家庭!!)無論如何,你是否知道需要的安全問題/配置,使用派生的prinicpal對象。我已經實現了上面的子類並獲取了一個異常讀取「UserPrincpalEx類型的主體對象不能用於查詢這個商店」。有任何想法嗎?謝謝。 – brumScouse 2012-07-12 13:00:04

7

爲了擴大上述我敲了一個擴展方法來調用ExtensionGet。它使用反射來獲取您必須繼承的受保護方法。您可能需要使用這個,如果你是從Groups.Members返回UserPrincipalObjects,例如

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

+1這是非常方便的技巧。我就像「哦,現在我需要繼承!」你只是想了解這個方法是受保護的,並且設計爲通過子類訪問。我想起了一個話題我寫了一篇關於如何利用.NET反射來「突破」 OOP概念:http://mazdev.blogspot.ae/2011/05/breaching-object-oriented-programming.html – Mzn 2014-06-18 08:16:29

+0

什麼價值的關鍵字不是字符串值。像'accountExpires'屬性中的'System._comObject'。 – 2016-11-01 21:04:11