The following code works fine on my test environment (the test environment
is joined to the INTRA domain):
public bool IsMemberOf(string userAccount, string groupAccount)
{
UserPrincipal up = GetUserPrincipalByAccount(userAccount);
GroupPrincipal gp = GetGroupPrincipalByAccount(groupAccount);
return up.IsMemberOf(gp);
}
protected UserPrincipal GetUserPrincipalByAccount(string account)
{
Account a = new Account(account);
if (!principalContexts.ContainsKey(a.Domain)) return null;
PrincipalContext ctx = principalContexts[a.Domain].Context;
if (ctx == null) return null;
UserPrincipal p = UserPrincipal.FindByIdentity(ctx, a.UserName);
return p;
}
private GroupPrincipal GetGroupPrincipalByAccount(string groupAccount)
{
Account a = new Account(groupAccount);
if (!principalContexts.ContainsKey(a.Domain)) return null;
PrincipalContext ctx = principalContexts[a.Domain].Context;
if (ctx == null) return null;
GroupPrincipal p = GroupPrincipal.FindByIdentity(ctx, a.UserName);
return p;
}
public class Account:IEquatable<Account>
{
private string domain = string.Empty;
public string Domain
{
get { return domain; }
set
{
if (value != null) domain = value.ToUpper();
else domain = value;
if (domain == Environment.MachineName || domain ==
"LOCALHOST") domain = ".";
}
}
private string userName = string.Empty;
public string UserName
{
get { return userName; }
set
{
if (value != null) userName = value.ToLower();
else userName = value;
}
}
public Account(string accountString)
{
int i = accountString.IndexOf('\\');
userName = accountString;
if (i >= 0)
{
Domain = accountString.Substring(0, i);
if (accountString.Length > i) userName =
accountString.Substring(i + 1).ToLower();
}
else domain = ".";
}
/// <summary>
/// Get regular account name, format as "DOMAIN\username"
/// </summary>
/// <returns>regular account name string</returns>
public override string ToString()
{
string toString = "";
if (domain == ".") toString = Environment.MachineName;
else toString = domain;
return toString + "\\" + userName;
}
#region IEquatable<Account> Members
public bool Equals(Account other)
{
return (domain == other.Domain && userName == other.userName);
}
#endregion
}
When I call the function IsMemberOf("aLocalUser", "aLocalGroup") on the
EX.DMZ.corp(which is my production environment), it failed by the exception:
System.Runtime.InteropServices.COMException (0x80070035): The network path
was not found. at System.DirectoryServices.DirectoryEntry.Bind(Boolean
throwIfFail) at System.DirectoryServices.DirectoryEntry.Bind() at
System.DirectoryServices.DirectoryEntry.get_AdsObject() at
System.DirectoryServices.PropertyValueCollection.PopulateList() at
System.DirectoryServices.PropertyValueCollection..ctor(DirectoryEntry entry,
String propertyName) at
System.DirectoryServices.PropertyCollection.get_Item(String propertyName) at
System.DirectoryServices.AccountManagement.SAMStoreCtx.ResolveCrossStoreRefToPrincipal(Object
o) at
System.DirectoryServices.AccountManagement.SAMMembersSet.MoveNextForeign() at
System.DirectoryServices.AccountManagement.SAMMembersSet.MoveNext() at
System.DirectoryServices.AccountManagement.PrincipalCollectionEnumerator.MoveNext()
at
System.DirectoryServices.AccountManagement.PrincipalCollection.ContainsEnumTest(Principal
principal) at
System.DirectoryServices.AccountManagement.PrincipalCollection.Contains(Principal
principal) at
System.DirectoryServices.AccountManagement.Principal.IsMemberOf(GroupPrincipal
group) at Pei.DirectoryServices.ADHelper.IsMemberOf(String userAccount,
String groupAccount)
If I remove all non-local user accounts (such as DMZ\xxxx or INTRA\xxxxx,)
from the "aLocalGroup", the function works again!
I have right set the user credentials to connect the context stores, and can
create new user account to the LocalMachine, DMZ and INTRA domain by the
credentials.
I continue try resolving the problem by changing credetials for these
stores, null user, DMZ\DMZADMIN, INTRA\ADMIN, and I have changed Application
Pool Identity from LocalSystem to NetworkService, all failed by the same
exception!
Any idea?
--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services Programming"
http://www.directoryprogramming.net
"dotAge" <dot...@discussions.microsoft.com> wrote in message
news:FEF3D268-E6DF-4A37...@microsoft.com...
foreach (Principal p in gp.Members)
{
if (up.Sid == p.Sid) return true;
}
The enumerator gp.Members throws the same exception.
continue try adding the impersonation code:
using (Impersonation impersonation = new Impersonation("DMZADMIN", "dmz",
"*******")) {
//.......
}
it throwed a different exception:
System.DirectoryServices.AccountManagement.PrincipalOperationException: An
error (5) occurred while enumerating the group membership. The member's SID
could not be resolved. at
System.DirectoryServices.AccountManagement.SAMMembersSet.IsLocalMember(Byte[]
sid) at
System.DirectoryServices.AccountManagement.SAMMembersSet.MoveNextLocal() at
System.DirectoryServices.AccountManagement.SAMMembersSet.MoveNext() at
System.DirectoryServices.AccountManagement.PrincipalCollectionEnumerator.MoveNext()
at
System.DirectoryServices.AccountManagement.PrincipalCollection.ContainsEnumTest(Principal
principal) at
System.DirectoryServices.AccountManagement.PrincipalCollection.Contains(Principal
principal) at
System.DirectoryServices.AccountManagement.Principal.IsMemberOf(GroupPrincipal group)
I think may be there is a bug in the GroupPrincipal.Members enumorator with
the scenario. No other way, I have to give up it, replace with the following
code, it worked well:
UserPrincipal up = GetUserPrincipalByAccount(userAccount);
GroupPrincipal gp = GetGroupPrincipalByAccount(groupAccount);
DirectoryEntry de = (DirectoryEntry)gp.GetUnderlyingObject();
object m = de.Invoke("Members");
foreach (object u in (IEnumerable)m)
{
DirectoryEntry ude = new DirectoryEntry(u);
SecurityIdentifier sid = new
SecurityIdentifier((byte[])ude.Properties["objectSid"].Value, 0);
if (sid == up.Sid) return true;
}
return false;
--
Joe Kaplan-MS MVP Directory Services Programming
Co-author of "The .NET Developer's Guide to Directory Services Programming"
http://www.directoryprogramming.net
"dotAge" <dot...@discussions.microsoft.com> wrote in message
news:64B48D8D-2CC5-4A1D...@microsoft.com...