【问题标题】:Improving performance of System.DirectoryServices.AccountManagement提高 System.DirectoryServices.AccountManagement 的性能
【发布时间】:2010-03-09 13:51:32
【问题描述】:

我有一个程序可以让我管理我们用于演示软件的终端服务器上的用户。我一直在尝试提高向系统添加用户的性能(它添加主帐户,然后在需要时添加子帐户,例如,如果我有一个 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() 并不昂贵。您还有其他建议可以帮助加快这一进程吗?

编辑—— 正常情况是用户存在,但子用户很可能不存在,但它可以存在。

【问题讨论】:

    标签: c# .net performance directoryservices account-management


    【解决方案1】:

    我找到了解决方案

    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 =&gt;Regex.IsMatch(...))).ToDictionary(a =&gt; a.SamAccountName); 的奇怪调用是因为主要搜索器不缓存结果。请参阅几天前的my question

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-19
      • 2019-03-26
      • 2012-03-19
      • 1970-01-01
      • 2014-04-18
      • 2014-01-04
      相关资源
      最近更新 更多