编程语言
首页 > 编程语言> > c#-提高System.DirectoryServices.AccountManagement的性能

c#-提高System.DirectoryServices.AccountManagement的性能

作者:互联网

我有一个程序,可以让我在用于演示软件的终端服务器上管理用户.我一直在尝试提高向系统添加用户的性能(先添加主帐户,然后在需要时添加子帐户,例如,如果我有一个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();
        }
    }
}

逐步执行代码,我发现用户= 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.

标签:directoryservices,performance,account-management,c,net
来源: https://codeday.me/bug/20191210/2100034.html