Reputation: 3238
I am creating accounts and setting properties on them using System.DirectoryServices.AccountManagement
in .NET 4.5. One of the requirements is that the group membership (including Primary Group) be copied from a template account. The code includes the following:
foreach (var group in userPrincipal.GetGroups()) {
var groupPrincipal = (GroupPrincipal) @group;
if (groupPrincipal.Sid != templatePrimaryGroup.Sid) {
groupPrincipal.Members.Remove(userPrincipal);
groupPrincipal.Save();
}
}
This works about 90% of the time. The rest of the time, it fails with:
System.DirectoryServices.DirectoryServicesCOMException was unhandled HResult=-2147016656 Message=There is no such object on the server.
Source=System.DirectoryServices ErrorCode=-2147016656 ExtendedError=8333 ExtendedErrorMessage=0000208D: NameErr: DSID-03100213, problem 2001 (NO_OBJECT), data 0, best match of: 'OU=Whatever,DC=domain,DC=local`
on the GetGroups
call. My guess is that there is a race condition of some sort with the user not being fully created before I next go to access it. I know from diagnostic logging that I am going against the same domain controller each time (it's using the same PrincipalContext
so that matches my expectation) so it's not a replication issue.
Is my guess accurate? Is there a good way to handle this? I could just throw in a Sleep
but that seems like a cop-out at best and fragile at worst. So what is the right thing to do?
Upvotes: 2
Views: 2151
Reputation: 2010
Try something like:
int maxWait = 120;
int cnt = 0;
bool usable = false;
while (usable == false && cnt < maxWait)
{
try
{
foreach (var group in userPrincipal.GetGroups())
{
var groupPrincipal = (GroupPrincipal)@group;
if (groupPrincipal.Sid != templatePrimaryGroup.Sid)
{
groupPrincipal.Members.Remove(userPrincipal);
groupPrincipal.Save();
}
}
usable = true;
break;
}
catch
{
System.Threading.Thread.Sleep(500);
}
}
if (usable)
//All okay
;
else
//Do something
;
This way you can try for "a while". If it works good, if not do something like log an error, so you can run a fix-it script later.
Upvotes: 1