如何从C#中的Active Directory获取自定义字段?

如何从C#中的Active Directory获取自定义字段?,c#,active-directory,C#,Active Directory,我读过很多类似的问题,但似乎没有一个能解决我所看到的问题。如果我使用userprincipalname查询一个用户,我会得到一个包含34个属性的搜索结果。不会返回任何自定义属性。如果我再次使用自定义属性(如employeeNumber)进行查询,我将得到一个包含71个属性的结果。包括所有自定义属性 我的问题是在运行时没有employeeNumber,只有userprincipalname。我需要随时取回所有的自定义属性。希望这是有道理的。这是我的执业守则: string sid = ""; us

我读过很多类似的问题,但似乎没有一个能解决我所看到的问题。如果我使用userprincipalname查询一个用户,我会得到一个包含34个属性的搜索结果。不会返回任何自定义属性。如果我再次使用自定义属性(如employeeNumber)进行查询,我将得到一个包含71个属性的结果。包括所有自定义属性

我的问题是在运行时没有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 :(
}
和自定义搜索筛选器:

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;
}
var m始终为空字符串,即使所有AD条目都有一个employeeNumber


编辑:来自active directory:

我对如何修复您的第二种方法更为熟悉,因此我将首先回答这个问题。在搜索要显示的属性时,需要在中指定属性

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集合


对于第一个方法,我认为需要调用并传入属性以使其显示

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
{

非常感谢你的想法,但不幸的是,它们没有起作用。刷新缓存是个好主意,但值仍然是空字符串。另一个设置PropertiesToLoad的想法很好,但没有成功。我甚至更进一步地理解了您的推理,将employeeNumber添加到我的查询中,以尝试并强制加载它,如下所示:search.Filter=string.Format(&(ObjectClass=user)(|(employeeNumber=99999)(userprincipalname={0})),sid);嗯。您是否100%确定您要检索的员工在该属性中有值。我不知道,但如果没有设置值,它可能不会显示。看看,也许它能给你一个主意。我只是仔细检查了一下,它就在那里。我查询了雇员11663(我自己),得到了一个包含71个属性的对象。EmployeeNumber就是其中之一。再次使用我的名字、我的sid、我的userprincipalname进行查询,所有3个都返回了相同的对象,但减去employee number属性。我会查一下你的老问题,谢谢。我添加了一张显示我的雇员编号的广告图片。
[DirectoryObjectClass(“用户”)]
有帮助吗?我被难住了,一切看起来都很正常,我不知道我们都错过了什么。
[DirectoryRdnPrefix("CN")]
[DirectoryObjectClass("user")] //Maybe this will fix it???
public class UserPrincipalExtension : UserPrincipal
{