【发布时间】:2012-03-02 21:12:28
【问题描述】:
我已成功使用 AccountManagement 代码检索基本 AD 信息,但它只返回关于返回对象的一组非常有限的信息。如何使用 AccountManagement 功能从 AD 获取扩展信息。特别是在我的 AD 实例中似乎被称为职称或头衔。
我知道如何使用旧的 DirectoryServices,但我想知道如何使用新的命名空间。
【问题讨论】:
我已成功使用 AccountManagement 代码检索基本 AD 信息,但它只返回关于返回对象的一组非常有限的信息。如何使用 AccountManagement 功能从 AD 获取扩展信息。特别是在我的 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 命名空间及其可扩展性故事的所有信息:
更新:抱歉 - 这是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);
}
}
【讨论】:
DirectoryObjectClass 从“Person”更改为“User”之前,我遇到了同样的错误。 (希望你在一年前就知道了)
为了增强上面的内容,我敲了一个扩展方法来调用 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;
}
}
【讨论】:
System._comObject 在 accountExpires 属性中一样。
有更简单的方法可以获取该信息。这是我在 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
【讨论】:
(ldapEntry.GetUnderlyingObject() as DirectoryEntry)?.Properties["Title"].Value ?? "EMPTY"
要扩展 Programmierus 的评论,这里有一个在 C# 中即时执行此操作的简单方法。
public static string GetProperty(UserPrincipal userPrincipal, string property)
{
DirectoryEntry d = (DirectoryEntry)userPrincipal.GetUnderlyingObject();
return d.Properties[property]?.Value?.ToString();
}
【讨论】: