gpt4 book ai didi

c# - 事件目录 : DirectoryEntry member list <> GroupPrincipal. GetMembers()

转载 作者:太空宇宙 更新时间:2023-11-03 20:57:13 26 4
gpt4 key购买 nike

我有一个小组,我们称它为 GotRocks。我正在尝试获取其所有成员,但在 DirectoryEntry 和 AccountManagement 之间我得到的结果在计数方面截然不同。以下是按成员检索方法分类的计数:

Method 1: DirectoryEntry.PropertyName.member = 350
Method 2: AccountManagement.GroupPrincipal.GetMembers(false) = 6500
Method 2: AccountManagement.GroupPrincipal.GetMembers(true) = 6500

作为完整性检查,我进入 ADUC 并从组中提取成员列表,默认情况下限制为 2,000。这里重要的是 ADUC 似乎验证了 AccountManagement 结果。我也检查了 Children 属性,但它是空白的。此外,DirectoryEntry 中列出的成员都不属于 SchemaName 组 - 他们都是用户。

我认为这不是代码问题,但可能是不了解 DirectoryEntry 和 GetMembers 方法如何检索组成员。谁能解释为什么 DirectoryEntry 成员列表会产生与 GetMembers 递归函数不同的结果?我需要注意某种方法或属性吗?注意:我构建了一个函数,它将通过“member;range={0}-{1}”查询 DirectoryEntry,其中循环以 1,500 个 block 的形式获取成员。我在这里完全不知所措。

DirectoryEntry 返回如此少的结果这一事实是有问题的,因为我想使用 DirectoryEntry 的一个简单事实是走这条路至少比 AccountManagement 快两个数量级(即秒表时间为 1,100 毫秒,而250,000 毫秒)。

更新 1:方法:

方法一:DirectoryEntry

private List<string> GetGroupMemberList(string strPropertyValue, string strActiveDirectoryHost, int intActiveDirectoryPageSize)
{
// Variable declaration(s).
List<string> listGroupMemberDn = new List<string>();
string strPath = strActiveDirectoryHost + "/<GUID=" + strPropertyValue + ">";
string strMemberPropertyRange = null;
DirectoryEntry directoryEntryGroup = null;
DirectorySearcher directorySearcher = null;
SearchResultCollection searchResultCollection = null;
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms676302(v=vs.85).aspx
const int intIncrement = 1500;

// Load the DirectoryEntry.
try
{
directoryEntryGroup = new DirectoryEntry(strPath, null, null, AuthenticationTypes.Secure);

directoryEntryGroup.RefreshCache();
}
catch (Exception)
{ }

try
{
if (directoryEntryGroup.Properties["member"].Count > 0)
{
int intStart = 0;

while (true)
{
int intEnd = intStart + intIncrement - 1;

// Define the PropertiesToLoad attribute, which contains a range flag that LDAP uses to get a list of members in a pre-specified chunk/block of members that is defined by each loop iteration.
strMemberPropertyRange = string.Format("member;range={0}-{1}", intStart, intEnd);

directorySearcher = new DirectorySearcher(directoryEntryGroup)
{
Filter = "(|(objectCategory=person)(objectCategory=computer)(objectCategory=group))", // User, Contact, Group, Computer objects

SearchScope = SearchScope.Base,

PageSize = intActiveDirectoryPageSize,

PropertiesToLoad = { strMemberPropertyRange }
};

try
{
searchResultCollection = directorySearcher.FindAll();

foreach (SearchResult searchResult in searchResultCollection)
{
var membersProperties = searchResult.Properties;

// Find the property that starts with the PropertyName of "member;" and get all of its member values.
var membersPropertyNames = membersProperties.PropertyNames.OfType<string>().Where(n => n.StartsWith("member;"));

// For each record in the memberPropertyNames, get the PropertyName and add to the lest.
foreach (var propertyName in membersPropertyNames)
{
var members = membersProperties[propertyName];

foreach (string memberDn in members)
{
listGroupMemberDn.Add(memberDn);
}
}
}
}
catch (DirectoryServicesCOMException)
{
// When the start of the range exceeds the number of available results, an exception is thrown and we exit the loop.
break;
}

intStart += intIncrement;
}
}

return listGroupMemberDn;
}
finally
{
listGroupMemberDn = null;
strPath = null;
strMemberPropertyRange = null;
directoryEntryGroup.Close();
if(directoryEntryGroup != null) directoryEntryGroup.Dispose();
if (directorySearcher != null) directorySearcher.Dispose();
if(searchResultCollection != null) searchResultCollection.Dispose();
}
}

方法 2:AccountManagement(将 bolRecursive 切换为 true 或 false)。

private List<Guid> GetGroupMemberList(string strPropertyValue, string strDomainController, bool bolRecursive)
{
// Variable declaration(s).
List<Guid> listGroupMemberGuid = null;
GroupPrincipal groupPrincipal = null;
PrincipalSearchResult<Principal> listPrincipalSearchResult = null;
List<Principal> listPrincipalNoNull = null;
PrincipalContext principalContext = null;
ContextType contextType;
IdentityType identityType;

try
{
listGroupMemberGuid = new List<Guid>();

contextType = ContextType.Domain;

principalContext = new PrincipalContext(contextType, strDomainController);

// Setup the IdentityType. Use IdentityType.Guid because GUID is unique and never changes for a given object. Make sure that is what strPropertyValue is receiving.
// This is required, otherwise you will get a MultipleMatchesException error that says "Multiple principals contain a matching Identity."
// This happens when you have two objects that AD thinks match whatever you're passing to UserPrincipal.FindByIdentity(principalContextDomain, strPropertyValue)
identityType = IdentityType.Guid;

groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, identityType, strPropertyValue);

if (groupPrincipal != null)
{
// Get all members that the group contains and add it to the list.
// Note: The true flag in GetMembers() specifies a recursive search, which enables the application to search a group recursively and return only principal objects that are leaf nodes.
listPrincipalSearchResult = groupPrincipal.GetMembers(bolRecursive);

// Remove the nulls from the list, otherwise the foreach loop breaks prematurly on the first null found and misses all other object members.
listPrincipalNoNull = listPrincipalSearchResult.Where(item => item.Name != null).ToList();

foreach (Principal principal in listPrincipalNoNull)
{
listGroupMemberGuid.Add((Guid)principal.Guid);
}
}

return listGroupMemberGuid;
}
catch (MultipleMatchesException)
{
// Multiple principals contain a matching identity.
// In other words, the same property value was found on more than one record in either of the six attributes that are listed within the IdentityType enum.
throw new MultipleMatchesException(strPropertyValue);
}
finally
{
// Cleanup objects.
listGroupMemberGuid = null;
if(listPrincipalSearchResult != null) listPrincipalSearchResult.Dispose();
if(principalContext != null) principalContext.Dispose();
if(groupPrincipal != null) groupPrincipal.Dispose();
}
}

更新 2:

public static void Main()
{
Program objProgram = new Program();

// Other stuff here.

objProgram.GetAllUserSingleDc();

// Other stuff here.
}

private void GetAllUserSingleDc()
{
string strDomainController = "domain.com";
string strActiveDirectoryHost = "LDAP://" + strDomainController;
int intActiveDirectoryPageSize = 1000;
string[] strAryRequiredProperties = null;
DirectoryEntry directoryEntry = null;
DirectorySearcher directorySearcher = null;
SearchResultCollection searchResultCollection = null;
DataTypeConverter objConverter = null;
Type fieldsType = null;

fieldsType = typeof(AdUserInfoClass);

objConverter = new DataTypeConverter();

directoryEntry = new DirectoryEntry(strActiveDirectoryHost, null, null, AuthenticationTypes.Secure);

directorySearcher = new DirectorySearcher(directoryEntry)
{
//Filter = "(|(objectCategory=person)(objectCategory=computer)(objectCategory=group))", // User, Contact, Group, Computer objects
Filter = "(sAMAccountName=GotRocks)", // Group

SearchScope = SearchScope.Subtree,

PageSize = intActiveDirectoryPageSize

PropertiesToLoad = { "isDeleted","isCriticalSystemObject","objectGUID","objectSid","objectCategory","sAMAccountName","sAMAccountType","cn","employeeId",
"canonicalName","distinguishedName","userPrincipalName","displayName","givenName","sn","mail","telephoneNumber","title","department",
"description","physicalDeliveryOfficeName","manager","userAccountControl","accountExpires","lastLogon","logonCount","lockoutTime",
"primaryGroupID","pwdLastSet","uSNCreated","uSNChanged","whenCreated","whenChanged","badPasswordTime","badPwdCount","homeDirectory",
"dNSHostName" }
};

searchResultCollection = directorySearcher.FindAll();

try
{
foreach (SearchResult searchResult in searchResultCollection)
{
clsAdUserInfo.GidObjectGuid = objConverter.ConvertByteAryToGuid(searchResult, "objectGUID");
clsAdUserInfo.StrDirectoryEntryPath = strActiveDirectoryHost + "/<GUID=" + clsAdUserInfo.GidObjectGuid + ">";
clsAdUserInfo.StrSchemaClassName = new DirectoryEntry(clsAdUserInfo.StrDirectoryEntryPath, null, null, AuthenticationTypes.Secure).SchemaClassName;

if (clsAdUserInfo.StrSchemaClassName == "group")
{
// Calling the functions here.
List<string> listGroupMemberDnMethod1 = GetGroupMemberListStackOverflow(clsAdUserInfo.GidObjectGuid.ToString(), strActiveDirectoryHost, intActiveDirectoryPageSize);

List<Guid> listGroupMemberGuidMethod2 = GetGroupMemberList(clsAdUserInfo.GidObjectGuid.ToString(), strDomainController, false)
}
// More stuff here.
}
}
finally
{
// Cleanup objects.
// Class constructors.
objProgram = null;
clsAdUserInfo = null;
// Variables.
intActiveDirectoryPageSize = -1;
strActiveDirectoryHost = null;
strDomainController = null;
strAryRequiredProperties = null;
directoryEntry.Close();
if(directoryEntry !=null) directoryEntry.Dispose();
if(directorySearcher != null) directorySearcher.Dispose();
if(searchResultCollection != null) searchResultCollection.Dispose();
objConverter = null;
fieldsType = null;
}
}

更新 3:

下面是我正在使用的命名空间列表。

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Security.Principal;
using System.Text;
using System.Linq;
using System.Collections;

更新 4:Program.cs

using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;
using System.Security.Principal;
using System.Text;
using System.Linq;

namespace activeDirectoryLdapExamples
{
public class Program
{
public static void Main()
{
Program objProgram = new Program();
objProgram.GetAllUserSingleDc();
}

#region GetAllUserSingleDc
private void GetAllUserSingleDc()
{
Program objProgram = new Program();
string strDomainController = "EnterYourDomainhere";
string strActiveDirectoryHost = "LDAP://" + strDomainController;
int intActiveDirectoryPageSize = 1000;
DirectoryEntry directoryEntry = null;
DirectorySearcher directorySearcher = null;
SearchResultCollection searchResultCollection = null;
DataTypeConverter objConverter = null;

objConverter = new DataTypeConverter();

directoryEntry = new DirectoryEntry(strActiveDirectoryHost, null, null, AuthenticationTypes.Secure);

directorySearcher = new DirectorySearcher(directoryEntry)
{
Filter = "(sAMAccountName=GotRocks)", // Group

SearchScope = SearchScope.Subtree,

PageSize = intActiveDirectoryPageSize,

PropertiesToLoad = { "isDeleted","isCriticalSystemObject","objectGUID","objectSid","objectCategory","sAMAccountName","sAMAccountType","cn","employeeId",
"canonicalName","distinguishedName","userPrincipalName","displayName","givenName","sn","mail","telephoneNumber","title","department",
"description","physicalDeliveryOfficeName","manager","userAccountControl","accountExpires","lastLogon","logonCount","lockoutTime",
"primaryGroupID","pwdLastSet","uSNCreated","uSNChanged","whenCreated","whenChanged","badPasswordTime","badPwdCount","homeDirectory",
"dNSHostName" }
};

searchResultCollection = directorySearcher.FindAll();

try
{
foreach (SearchResult searchResult in searchResultCollection)
{
Guid? gidObjectGuid = objConverter.ConvertByteAryToGuid(searchResult, "objectGUID");
string StrSamAccountName = objConverter.ConvertToString(searchResult, "sAMAccountName");
// Get new DirectoryEntry and retrieve the SchemaClassName from it by binding the current objectGUID to it.
string StrDirectoryEntryPath = strActiveDirectoryHost + "/<GUID=" + gidObjectGuid + ">";
string StrSchemaClassName = new DirectoryEntry(StrDirectoryEntryPath, null, null, AuthenticationTypes.Secure).SchemaClassName;

#region GetGroupMembers
if (StrSchemaClassName == "group")
{
// FAST!
var watch = System.Diagnostics.Stopwatch.StartNew();
List<string> listGroupMemberDn = GetGroupMemberList(gidObjectGuid.ToString(), strActiveDirectoryHost, intActiveDirectoryPageSize);
watch.Stop();
var listGroupMemberDnElapsedMs = watch.ElapsedMilliseconds;

// SLOW!
watch = System.Diagnostics.Stopwatch.StartNew();
List<Guid> listGroupMemberGuidRecursiveTrue = GetGroupMemberList(gidObjectGuid.ToString(), strDomainController, true);
watch.Stop();
var listGroupMemberGuidRecursiveTrueElapsedMs = watch.ElapsedMilliseconds;

watch = System.Diagnostics.Stopwatch.StartNew();
List<Guid> listGroupMemberGuidRecursiveFalse = GetGroupMemberList(gidObjectGuid.ToString(), strDomainController, false);
watch.Stop();
var listGroupMemberGuidRecursiveFalseElapsedMs = watch.ElapsedMilliseconds;

////// Display all members of the list.
//listGroupMemberDn.ForEach(item => Console.WriteLine("Member GUID: {0}", item));
//listGroupMemberGuidRecursiveTrue.ForEach(item => Console.WriteLine("Member GUID: {0}", item));
//listGroupMemberGuidRecursiveFalse.ForEach(item => Console.WriteLine("Member GUID: {0}", item));

Console.WriteLine("objectGUID: {0}", gidObjectGuid);
Console.WriteLine("sAMAccountName: {0}", strSamAccountName);

// Result: 350
Console.WriteLine("\nlistGroupMemberDn Count Members: {0}", listGroupMemberDn.Count);
Console.WriteLine("Total RunTime listGroupMemberDnElapsedMs (in milliseconds): {0}", listGroupMemberDnElapsedMs);

// Result: 6500
Console.WriteLine("\nlistGroupMemberGuidRecursiveTrue Count Members: {0}", listGroupMemberGuidRecursiveTrue.Count);
Console.WriteLine("Total RunTime listGroupMemberGuidRecursiveTrueElapsedMs (in milliseconds): {0}", listGroupMemberGuidRecursiveTrueElapsedMs);

// Result: 6500
Console.WriteLine("\nlistGroupMemberGuidRecursiveFalse Count Members: {0}", listGroupMemberGuidRecursiveFalse.Count);
Console.WriteLine("Total RunTime listGroupMemberGuidRecursiveFalseElapsedMs (in milliseconds): {0}", listGroupMemberGuidRecursiveFalseElapsedMs);
Console.WriteLine("\n");
}
#endregion

#region CurrentSearchResult
else
{
Console.WriteLine("ObjectGuid = {0}", gidObjectGuid);
Console.WriteLine("SamAccountName = {0}", strSamAccountName);

}
#endregion
}

Console.WriteLine("\nPress any key to continue.");
Console.ReadKey();
}
finally
{
objProgram = null;
intActiveDirectoryPageSize = -1;
strActiveDirectoryHost = null;
strDomainController = null;
directoryEntry.Close();
if (directoryEntry != null) directoryEntry.Dispose();
if (directorySearcher != null) directorySearcher.Dispose();
if (searchResultCollection != null) searchResultCollection.Dispose();
objConverter = null;
}
}
#endregion

#region GetGroupMemberListGuid
private List<Guid> GetGroupMemberList(string strPropertyValue, string strDomainController, bool bolRecursive)
{
List<Guid> listGroupMemberGuid = null;
List<Principal> listPrincipalNoNull = null;
GroupPrincipal groupPrincipal = null;
PrincipalSearchResult<Principal> listPrincipalSearchResult = null;
PrincipalContext principalContext = null;
ContextType contextType;
IdentityType identityType;

try
{
listGroupMemberGuid = new List<Guid>();

contextType = ContextType.Domain;

principalContext = new PrincipalContext(contextType, strDomainController);

identityType = IdentityType.Guid;

groupPrincipal = GroupPrincipal.FindByIdentity(principalContext, identityType, strPropertyValue);

if (groupPrincipal != null)
{
listPrincipalSearchResult = groupPrincipal.GetMembers(bolRecursive);

listPrincipalNoNull = listPrincipalSearchResult.Where(item => item.Name != null).ToList();

foreach (Principal principal in listPrincipalNoNull)
{
listGroupMemberGuid.Add((Guid)principal.Guid);
}
}

return listGroupMemberGuid;
}
catch (MultipleMatchesException)
{
throw new MultipleMatchesException(strPropertyValue);
}
finally
{
// Cleanup objects.
listGroupMemberGuid = null;
listPrincipalNoNull = null;
principalContext = null;
if (groupPrincipal != null) groupPrincipal.Dispose();
if (listPrincipalSearchResult != null) listPrincipalSearchResult.Dispose();
if (principalContext != null) principalContext.Dispose();
}
}
#endregion

#region GetGroupMemberListDn
private List<string> GetGroupMemberList(string strPropertyValue, string strActiveDirectoryHost, int intActiveDirectoryPageSize)
{
List<string> listGroupMemberDn = new List<string>();
string strPath = strActiveDirectoryHost + "/<GUID=" + strPropertyValue + ">";
const int intIncrement = 1500; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms676302(v=vs.85).aspx

var members = new List<string>();

// The count result returns 350.
var group = new DirectoryEntry(strPath, null, null, AuthenticationTypes.Secure);
//var group = new DirectoryEntry($"LDAP://{"EnterYourDomainHere"}/<GUID={strPropertyValue}>", null, null, AuthenticationTypes.Secure);

while (true)
{
var memberDns = group.Properties["member"];
foreach (var member in memberDns)
{
members.Add(member.ToString());
}

if (memberDns.Count < intIncrement) break;

group.RefreshCache(new[] { $"member;range={members.Count}-*" });
}
return members;
}
#endregion

#region DataTypeConvert
private class DataTypeConverter
{
public DataTypeConverter() { }

public String ConvertToString(SearchResult searchResult, string strPropertyName)
{
String bufferObjectString = null;

try
{
bufferObjectString = (String)this.GetPropertyValue(searchResult, strPropertyName);

if (string.IsNullOrEmpty(bufferObjectString))
{
return null;
}
else
{
return bufferObjectString;
}
}
finally
{
bufferObjectString = null;
}
}

public Guid? ConvertByteAryToGuid(SearchResult searchResult, string strPropertyName)
{
Guid? bufferObjectGuid = null;

try
{
bufferObjectGuid = new Guid((Byte[])(Array)this.GetPropertyValue(searchResult, strPropertyName));

if (bufferObjectGuid == null || bufferObjectGuid == Guid.Empty)
{
throw new NullReferenceException("The field " + strPropertyName + ", of type GUID, can neither be NULL nor empty.");
}
else
{
return bufferObjectGuid;
}
}
finally
{
bufferObjectGuid = null;
}
}
}
#endregion
}
}

最佳答案

最后一个代码块(更新 2)就是答案!

读取member 属性的代码比需要的更复杂。它返回有偏差的结果可能是有原因的,但我并没有仔细看,因为您根本不需要使用 DirectorySearcher。我刚刚重写了它。

这是最简单的形式:

private static List<string> GetGroupMemberList(string groupGuid, string domainDns) {
var members = new List<string>();

var group = new DirectoryEntry($"LDAP://{domainDns}/<GUID={groupGuid}>", null, null, AuthenticationTypes.Secure);

while (true) {
var memberDns = group.Properties["member"];
foreach (var member in memberDns) {
members.Add(member.ToString());
}

if (memberDns.Count == 0) break;

try {
group.RefreshCache(new[] {$"member;range={members.Count}-*", "member"});
} catch (System.Runtime.InteropServices.COMException e) {
if (e.ErrorCode == unchecked((int) 0x80072020)) { //no more results
break;
}
throw;
}
}
return members;
}

这样调用它:

var members = GetGroupMemberList("00000000-0000-0000-0000-000000000000", "domain.com");

这不是递归的。要使其递归,您必须从每个成员创建一个新的 DirectoryEntry 并测试它是否是一个组,然后获取该组的成员。

我打开了代码,所以这是递归版本。它很慢,因为它必须绑定(bind)到每个成员以查看它是否是一个组。

这不是防弹的。在某些情况下,您可能会得到奇怪的结果(例如,如果您的用户位于组中受信任的外部域中)。

private static List<string> GetGroupMemberList(string groupGuid, string domainDns, bool recurse = false) {
var members = new List<string>();

var group = new DirectoryEntry($"LDAP://{domainDns}/<GUID={groupGuid}>", null, null, AuthenticationTypes.Secure);

while (true) {
var memberDns = group.Properties["member"];
foreach (var member in memberDns) {
if (recurse) {
var memberDe = new DirectoryEntry($"LDAP://{member}");
if (memberDe.Properties["objectClass"].Contains("group")) {
members.AddRange(GetGroupMemberList(
new Guid((byte[]) memberDe.Properties["objectGuid"].Value).ToString(), domainDns,
true));
} else {
members.Add(member.ToString());
}
} else {
members.Add(member.ToString());
}
}

if (memberDns.Count == 0) break;

try {
group.RefreshCache(new[] {$"member;range={members.Count}-*", "member"});
} catch (System.Runtime.InteropServices.COMException e) {
if (e.ErrorCode == unchecked((int) 0x80072020)) { //no more results
break;
}
throw;
}
}
return members;
}

更新:我确实必须编辑您的 GetMembers 示例,因为它一直向我抛出异常。我注释掉了 .Where 行并更改了将成员添加到列表的 foreach 循环:

        //listPrincipalNoNull = listPrincipalSearchResult.Where(item => item.Name != null).ToList();
if (groupPrincipal != null) {
foreach (Principal principal in listPrincipalSearchResult) {
listGroupMemberGuid.Add(((DirectoryEntry)principal.GetUnderlyingObject()).Guid);
}
}

当然,这是在编译一个 Guid 列表而不是 DN。

更新 2:这是一个版本,它也拉取将组作为主要组(但未在 member 中列出)的用户组的属性)。 GetMembers 似乎是这样做的。用户创建的组成为主要组会很奇怪,但在技术上是可行的。部分内容复制自此处的答案:How to retrieve Users in a Group, including primary group users

private List<string> GetGroupMemberList(string strPropertyValue, string strActiveDirectoryHost, int intActiveDirectoryPageSize)
{
// Variable declaration(s).
List<string> listGroupMemberDn = new List<string>();
string strPath = strActiveDirectoryHost + "/<GUID=" + strPropertyValue + ">";
const int intIncrement = 1500; // https://msdn.microsoft.com/en-us/library/windows/desktop/ms676302(v=vs.85).aspx

var members = new List<string>();

// The count result returns 350.
var group = new DirectoryEntry(strPath, null, null, AuthenticationTypes.Secure);
//var group = new DirectoryEntry($"LDAP://{"EnterYourDomainHere"}/<GUID={strPropertyValue}>", null, null, AuthenticationTypes.Secure);

while (true)
{
var memberDns = group.Properties["member"];
foreach (var member in memberDns)
{
members.Add(member.ToString());
}

if (memberDns.Count < intIncrement) break;

group.RefreshCache(new[] { $"member;range={members.Count}-*" });
}

//Find users that have this group as a primary group
var secId = new SecurityIdentifier(group.Properties["objectSid"][0] as byte[], 0);

/* Find The RID (sure exists a best method)
*/
var reg = new Regex(@"^S.*-(\d+)$");
var match = reg.Match(secId.Value);
var rid = match.Groups[1].Value;

/* Directory Search for users that has a particular primary group
*/
var dsLookForUsers =
new DirectorySearcher {
Filter = string.Format("(primaryGroupID={0})", rid),
SearchScope = SearchScope.Subtree,
PageSize = 1000,
SearchRoot = new DirectoryEntry(strActiveDirectoryHost)
};
dsLookForUsers.PropertiesToLoad.Add("distinguishedName");

var srcUsers = dsLookForUsers.FindAll();

foreach (SearchResult user in srcUsers)
{
members.Add(user.Properties["distinguishedName"][0].ToString());
}
return members;
}

关于c# - 事件目录 : DirectoryEntry member list <> GroupPrincipal. GetMembers(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49227795/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com