C# 仅从Active Directory获取已启用的帐户

C# 仅从Active Directory获取已启用的帐户,c#,active-directory,directoryservices,account-management,C#,Active Directory,Directoryservices,Account Management,我正在使用System.DirectoryServices.AccountManagement.dll处理Active Directory 获取“域用户”组中的所有用户 这将返回域中的所有用户,但我需要只获取已启用的用户 以下是一些示例代码: List<string> users = new List<string>(); PrincipalContext pcContext = GetPrincipalContext(); GroupPrincipal grp =

我正在使用
System.DirectoryServices.AccountManagement.dll
处理Active Directory 获取“域用户”组中的所有用户

这将返回域中的所有用户,但我需要只获取已启用的用户

以下是一些示例代码:

List<string> users = new List<string>();

PrincipalContext pcContext = GetPrincipalContext();

GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcContext,
                               IdentityType.Name,
                               "Domain Users");

foreach (Principal user in grp.GetMembers(true).OfType<UserPrincipal>())
{
    if (user.Enabled != false)
    {
        users.Add(user.Name);
    }
}
列表用户=新列表();
PrincipalContext pcContext=GetPrincipalContext();
GroupPrincipal grp=GroupPrincipal.FindByIdentity(pcContext,
IdentityType.Name,
“域名用户”);
foreach(grp.GetMembers(true).OfType()中的主要用户)
{
如果(user.Enabled!=false)
{
users.Add(user.Name);
}
}

其他组工作正常,但当组为“域用户”时,所有用户的
Enabled
属性值为
false
。这使得在没有对每个用户进行进一步查询的情况下,无法区分启用和禁用的用户。

UserPrinciple对象具有启用bool的属性

有一句话是这样说的:

如果主体尚未在存储中持久化,则此属性返回null。主体持久化后,默认启用的设置取决于存储。AD DS和AD LDS存储在持久化新主体时禁用它们,而SAM在持久化新主体时启用它们。应用程序只能在存储区中持久化此属性后将其设置为值

如果默认值为false,则可能与此相关

另外,MSDN论坛上有一篇关于的帖子,听起来和你的问题很相似。根据这篇文章,这里可能有一个解决方案:

我想我误解了。忽略我之前发布的内容。我想我 知道发生了什么。GetMembers方法显然没有加载 用户主体数据。我不知道是否有更好的解决办法, 但以下工作(至少在我的广告上):


解决此问题的一种方法是首先使用
PrincipalSearcher
类搜索启用的用户,然后使用主体的
IsMemberOf()方法

List用户=List();
PrincipalContext pcContext=GetPrincipalContext();
GroupPrincipal grp=GroupPrincipal.FindByIdentity(pcContext,IdentityType.Name,“域用户”);
UserPrincipal searchFilter=new UserPrincipal(pcContext){Enabled=true}
PrincipalSearcher=新PrincipalSearcher(搜索过滤器);
PrincipalSearchResult results=searcher.FindAll();
foreach(结果中的主要用户)
if(user.IsMemberOf(grp))
users.Add(user.SamAccountName);

这并不能解决问题,因为当被查询的组是“域用户”时,
Enabled
属性似乎没有正确填充。用户已经被持久化,因此答案的第一部分与问题无关。至于其余的,是的——我知道我可以做到这一点——问题表明,我们希望为
Enabled
属性提供一个正确的值,而不必进行任何额外的查询(特别是像foreach循环中那样,每个用户一个查询)。你引用的帖子甚至说这个解决方案太慢了,没有用处。你只需要帐户名吗?是否需要使用AccountManagement命名空间?除了存储名称之外,您是否对UserPrincipal对象执行任何操作?我之所以这么问,是因为使用DirectoryServices名称空间和DirectorySearcher以及LDAP筛选器可以更好地满足您的需求,例如:(&(objectclass=user)(memberOf=CN=Domain Users,dc=company,dc=com)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))它将返回该组中所有已启用的用户。randcd:我更喜欢使用AM名称空间,因为它提供了一个非常干净的API。我当然可以使用LDAP,但之后一切都变得更加复杂(特别是在用户只是域用户的成员的情况下,因为它是他们的主要组,因为在这种情况下它没有列在
memberOf
中)。ForEach循环中的“主体”实际上应该是“UserPrincipal”-“Enabled”不是可在Princpal对象上访问的方法或属性。至少不在.NET4.6.1中。这一切都可以通过System.DirectoryServices.AccountManagement命名空间完成。
// Add this to GetUserDetails
objUserDetails.EmployeeId = UserPrinical.EmployeeId;


// Then condition the add to only add enabled
if (objUserDetails.Enabled) {
    objUserDetails.Add(GetUserDetails(p.Name));
}
foreach (UserPrincipal user in group.GetMembers(false))
{
   UserPrincipal tempUser = UserPrincipal.FindByIdentity(context, user.SamAccountName);
   // use tempUser.Enabled
   // other code here
}
List<string> users = List<string>();
PrincipalContext pcContext = GetPrincipalContext();
GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcContext, IdentityType.Name, "Domain Users");
UserPrincipal searchFilter = new UserPrincipal(pcContext){ Enabled = true }
PrincipalSearcher searcher = new PrincipalSearcher(searchFilter);
PrincipalSearchResult<Principal> results = searcher.FindAll();
foreach (Principal user in results)
    if (user.IsMemberOf(grp))
        users.Add(user.SamAccountName);