我有一个程序,让我管理,我们用它来演示我们的软件我们的终端服务器上的用户。我一直在努力提高用户添加到系统中(它增加了主帐户,然后将其添加,如果需要的子账户,例如,如果我有demo1的用户与3分的用户,将创建demo1的,Demo1a,Demo1b的服务表现,和Demo1c。)
I have a program that will let me manage users on our terminal server that we use to demo our software. I have been trying to improve the performace of adding users to the system (It adds the main account then it adds sub accounts if needed, for example if I had a user of Demo1 and 3 sub users it would create Demo1, Demo1a, Demo1b, and Demo1c.)
private void AddUsers(UserInfo userInfo, InfinityInfo infinityInfo, int subUserStart)
{
using (GroupPrincipal r = GroupPrincipal.FindByIdentity(context, "Remote Desktop Users"))
using (GroupPrincipal u = GroupPrincipal.FindByIdentity(context, "Users"))
for(int i = subUserStart; i < userInfo.SubUsers; ++i)
{
string username = userInfo.Username;
if (i >= 0)
{
username += (char)('a' + i);
}
UserPrincipal user = null;
try
{
if (userInfo.NewPassword == null)
throw new ArgumentNullException("userInfo.NewPassword", "userInfo.NewPassword was null");
if (userInfo.NewPassword == "")
throw new ArgumentOutOfRangeException("userInfo.NewPassword", "userInfo.NewPassword was empty");
user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
if (user == null)
{
user = new UserPrincipal(context, username, userInfo.NewPassword, true);
user.UserCannotChangePassword = true;
user.PasswordNeverExpires = true;
user.Save();
r.Members.Add(user);
u.Members.Add(user);
}
else
{
user.Enabled = true;
user.SetPassword(userInfo.NewPassword);
}
IADsTSUserEx iad = (IADsTSUserEx)((DirectoryEntry)user.GetUnderlyingObject()).NativeObject;
iad.TerminalServicesInitialProgram = GenerateProgramString(infinityInfo);
iad.TerminalServicesWorkDirectory = Service.Properties.Settings.Default.StartInPath;
iad.ConnectClientDrivesAtLogon = 0;
user.Save();
r.Save();
u.Save();
OperationContext.Current.GetCallbackChannel<IRemoteUserManagerCallback>().FinishedChangingUser(username);
}
catch (Exception e)
{
string errorString = String.Format("Could not Add User:{0} Sub user:{1}", userInfo.Username, i);
try
{
if (user != null)
errorString += "\nSam Name: " + user.SamAccountName;
}
catch { }
OperationContext.Current.GetCallbackChannel<IRemoteUserManagerCallback>().UserException(errorString, e);
}
finally
{
if (user != null)
user.Dispose();
}
}
}
通过code步进我发现,用户= UserPrincipal.FindByIdentity(背景下,IdentityType.SamAccountName,用户名);
是昂贵的调用,服用5- 10秒每个循环。
Stepping through the code I have found that user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
is the expensive call, taking 5-10 seconds per loop.
我发现我是有每5〜10秒命中 GroupPrincipal.FindByIdentity()
打电话太让我感动出来的循环中,保存()
也不贵。你有什么其他的建议,以帮助加快这个吗?
I found I was having another 5-10 second hit on every GroupPrincipal.FindByIdentity()
call too so I moved it out of the loop, the Save()
is not expensive. Do you have any other recommendations to help speed this up?
编辑 - 正常情况下,将用户将存在,但它很可能是被副用户不存在,但可以存在
Edit -- The normal case would be the user will exist but it is likely that the sub-user does not exist, but it can exist.
我发现了一个soulution
I found a soulution
private void AddUsers(UserInfo userInfo, InfinityInfo infinityInfo, int subUserStart)
{
var userSerach = new UserPrincipal(context);
userSerach.SamAccountName = userInfo.Username + '*';
var ps = new PrincipalSearcher(userSerach);
var pr = ps.FindAll().ToList().Where(a =>
Regex.IsMatch(a.SamAccountName, String.Format(@"{0}\D", userInfo.Username))).ToDictionary(a => a.SamAccountName); // removes results like conversons12 from the search conversions1*
pr.Add(userInfo.Username, Principal.FindByIdentity(context, IdentityType.SamAccountName, userInfo.Username));
using (GroupPrincipal r = GroupPrincipal.FindByIdentity(context, "Remote Desktop Users"))
using (GroupPrincipal u = GroupPrincipal.FindByIdentity(context, "Users"))
for(int i = subUserStart; i < userInfo.SubUsers; ++i)
{
string username = userInfo.Username;
if (i >= 0)
{
username += (char)('a' + i);
}
UserPrincipal user = null;
try
{
if (userInfo.NewPassword == null)
throw new ArgumentNullException("userInfo.NewPassword", "userInfo.NewPassword was null");
if (userInfo.NewPassword == "")
throw new ArgumentOutOfRangeException("userInfo.NewPassword", "userInfo.NewPassword was empty");
if (pr.ContainsKey(username))
{
user = (UserPrincipal)pr[username];
user.Enabled = true;
user.SetPassword(userInfo.NewPassword);
}
else
{
user = new UserPrincipal(context, username, userInfo.NewPassword, true);
user.UserCannotChangePassword = true;
user.PasswordNeverExpires = true;
user.Save();
r.Members.Add(user);
u.Members.Add(user);
r.Save();
u.Save();
}
IADsTSUserEx iad = (IADsTSUserEx)((DirectoryEntry)user.GetUnderlyingObject()).NativeObject;
iad.TerminalServicesInitialProgram = GenerateProgramString(infinityInfo);
iad.TerminalServicesWorkDirectory = Service.Properties.Settings.Default.StartInPath;
iad.ConnectClientDrivesAtLogon = 0;
user.Save();
OperationContext.Current.GetCallbackChannel<IRemoteUserManagerCallback>().FinishedChangingUser(username);
}
finally
{
if (user != null)
{
user.Dispose();
}
}
}
}
它增加了对第一个用户几秒钟,但现在它的每个用户大约0.5秒后。 。在 ps.FindAll()了ToList的奇调用(),(一=&GT; Regex.IsMatch(...))。)ToDictionary(A =&GT; a.SamAccountName);
是因为原则上搜索不缓存结果。请参见我的问题从几天前。
It adds a few more seconds on the first user but now its about .5 seconds per user after that. The odd calling of the ps.FindAll().ToList().Where(a =>Regex.IsMatch(...))).ToDictionary(a => a.SamAccountName);
is because a principle searcher does not cache results. See my question from a few days ago.