我有一个程序可以让我管理我们用于演示软件的终端服务器上的用户。我一直在尝试提高将用户添加到系统的性能(它添加主帐户,然后在需要时添加子帐户,例如,如果我有一个 Demo1 用户和 3 个子用户,它将创建 Demo1、Demo1a、Demo1b、和 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();
}
}
}
单步执行代码,我发现 user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username);
是昂贵的调用,每个循环需要 5-10 秒。
我发现我在每个 GroupPrincipal.FindByIdentity()
调用中都有另外 5-10 秒的点击,所以我将它移出了循环,即 Save()
不贵。您有任何其他建议可以帮助加快这一过程吗?
编辑 -- 正常情况是用户会存在,但子用户很可能不存在,但它可以存在。
最佳答案
我找到了解决方案
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().Where(a =>Regex.IsMatch(...))).ToDictionary(a => a.SamAccountName);
的奇怪呼唤是因为原则搜索器不会缓存结果。参见 my question从几天前开始。
关于c# - 提高 System.DirectoryServices.AccountManagement 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2409432/