2015-07-01 68 views
5

我讀過很多類似的StackOverflow問題,但似乎沒有解決我看到的問題。如果我查詢使用userprincipalname的用戶,我會返回一個包含34個屬性的搜索結果。沒有任何自定義屬性被返回。如果我再次使用自定義屬性查詢,如employeeNumber我得到的結果有71個屬性。包括所有自定義屬性。如何從C#中的Active Directory獲取自定義字段?

我的問題是,我沒有在運行時employeeNumber,只是的UserPrincipalName。我需要隨時取回所有的自定義屬性。希望這是有道理的。這裏是我的做法代碼:

string sid = ""; 
using (PrincipalContext context = new PrincipalContext(ContextType.Domain)) 
{ 
    UserPrincipal user = UserPrincipal.Current; 
    //sid = user.SamAccountName; 
    sid = user.UserPrincipalName; 
    //sid = user.Sid.ToString(); 

    DirectoryEntry entry = user.GetUnderlyingObject() as DirectoryEntry; 
    if (entry.Properties.Contains("employeeNumber")) 
    { 
     //this doesn't work 
    } 
} 

DirectoryEntry ldapConnection = new DirectoryEntry("companyname.com"); 
ldapConnection.Path = "LDAP://DC=companyname,DC=com"; 
ldapConnection.AuthenticationType = AuthenticationTypes.Secure; 

DirectorySearcher search = new DirectorySearcher(ldapConnection); 
search.Filter = string.Format("(&(ObjectClass=user)(userprincipalname={0}))", sid); // <-- this doesn't get custom properties 
//search.Filter = string.Format("(employeeNumber={0})", "11663"); <-- this works 

var result = search.FindOne(); // FindOne(); 
if (result.Properties.Contains("employeeNumber")) 
{ 
    //this never happens either :(
} 

以上從未返回employeeNumber場,但如果我取消了第二search.Filter線和手動employeeNumber搜索我找到一個結果,它包含了所有的領域我需要。

編輯:我發現了一篇很好的MSDN文章Here,它描述瞭如何擴展UserPrincipal對象以獲取自定義屬性。唯一的問題是,即使我已驗證該屬性是在AD中設置的,它每次訪問它時都會給我一個空字符串!任何幫助表示讚賞。

編輯2:這是自定義主延伸代碼:

[DirectoryRdnPrefix("CN")] 
[DirectoryObjectClass("Person")] 
public class UserPrincipalExtension : UserPrincipal 
{ 
    public UserPrincipalExtension(PrincipalContext context) 
     : base(context) 
    { 
    } 

    public UserPrincipalExtension(PrincipalContext context, string samAccountName, string password, bool enabled) 
     : base(context, samAccountName, password, enabled) 
    { 
    } 

    public static new UserPrincipalExtension FindByIdentity(PrincipalContext context, IdentityType type, string identityValue) 
    { 
     return (UserPrincipalExtension)FindByIdentityWithType(context, typeof(UserPrincipalExtension), type, identityValue); 
    } 

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

      return searchFilter; 
     } 
    } 

    [DirectoryProperty("employeeNumber")] 
    public string EmployeeNumber 
    { 
     get 
     { 
      if (ExtensionGet("employeeNumber").Length != 1) 
       return string.Empty; 

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

而定製的搜索過濾器:

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

    public void SAMAccountName(string value, MatchType type) 
    { 
     this.AdvancedFilterSet("sAMAccountName", value, typeof(string), type); 
    } 
} 

用法:

UserPrincipalExtension filter = new UserPrincipalExtension(context); 
filter.AdvancedSearchFilter.SAMAccountName(UserPrincipal.Current.SamAccountName, MatchType.Equals); 
PrincipalSearcher search = new PrincipalSearcher(filter); 

foreach (var result in search.FindAll()) 
{ 
    var q = (UserPrincipalExtension)result; 
    var m = q.EmployeeNumber; 
} 

變種m是永遠的即使所有AD條目都有一個employeeNumber,也是空字符串。

編輯:從Active Directory:Active Directory

回答

1

我在如何解決你的第二個方法,所以我會回答這個問題首先更多知己。當您搜索要顯示的媒體資源時,您需要在DirectorySearcher.PropertiesToLoad中指定媒體資源。

DirectorySearcher search = new DirectorySearcher(ldapConnection); 
search.Filter = string.Format("(&(ObjectClass=user)(userprincipalname={0}))", sid); 
search.PropertiesToLoad.Add("employeeNumber"); 

var result = search.FindOne(); // FindOne(); 
if (result.Properties.Contains("employeeNumber")) 
{ 
    //This should now work. 
} 

它爲string.Format("(employeeNumber={0})", "11663");的原因是因爲你自動添加任何搜索條款被投入到PropertiesToLoad集合。


對於你的第一個方法,我認爲你需要調用DirectoryEntry.RefreshCache並傳入屬性,使其顯示出來。

string sid = ""; 
using (PrincipalContext context = new PrincipalContext(ContextType.Domain)) 
{ 
    UserPrincipal user = UserPrincipal.Current; 
    //sid = user.SamAccountName; 
    sid = user.UserPrincipalName; 
    //sid = user.Sid.ToString(); 

    DirectoryEntry entry = user.GetUnderlyingObject() as DirectoryEntry; 

    entry.RefreshCache(new[] {"employeeNumber"}); 

    if (entry.Properties.Contains("employeeNumber")) 
    { 

    } 
} 

但是,我不是100%確定,如果這將工作與否。


對於您的自定義用戶主體,我不確定什麼是錯的。我所看到的只是你在做什麼和我在一個我知道的項目中看到的唯一區別是你使用[DirectoryObjectClass("Person")],但我有[DirectoryObjectClass("user")]。也許這就是問題

[DirectoryRdnPrefix("CN")] 
[DirectoryObjectClass("user")] //Maybe this will fix it??? 
public class UserPrincipalExtension : UserPrincipal 
{ 
+0

非常感謝你的想法,但不幸的是他們沒有工作。刷新緩存是一個好主意,但值仍然是一個空字符串。你設置PropertiesToLoad的另一個想法是個好主意,但它不起作用。我甚至把你的推理進一步,並添加employeeNumber到我的查詢嘗試強制它加載,如下所示:search.Filter = string.Format(「(&(ObjectClass = user)(|(employeeNumber = 99999)(userprincipalname = {0})))「,sid); < - 您可以在我的OR條件中看到我的僞造員工編號。兩種情況都沒有運氣。 – BrianLegg

+0

嗯。您是否100%確定您正在檢索的員工在該財產中有價值?我不知道,但如果沒有設置值,它可能不會顯示出來。看看[這個老問題](http://stackoverflow.com/questions/14566887/how-to-set-a-binary-attribute-when-using-a-accountmanagement-extension-class),也許它可能會給你一個想法。 –

+0

我只是加倍檢查,它在那裏。我詢問僱員11663(我自己),然後我找回了一個有71個屬性的對象。 EmployeeNumber就是其中之一。再次使用我的名字查詢,然後是我的sid,然後是我的userprincipalname,所有3都給了我同樣的對象,但減去了員工編號屬性。我會檢查你的舊問題,謝謝。 – BrianLegg

相關問題