C# 在 foreach 循环期间暂停直到 Process.Exited

C# Pause during foreach loop until Process.Exited

所以我有一个遍历 DataGridView 的 foreach 循环。对于网格中的每一行,它都会执行 pspasswrd.exe 并更改本地帐户的密码。如何暂停 foreach 循环,直到进程完成,然后再移动到列表中的下一台计算机?

我不确定,我试过 WaitForExit 但这不可靠,因为它是同步的,所以如果需要很长时间,它会导致我的程序不响应。我需要使用 Process.Exited 但不确定如何正确执行此操作。

这是我的 foreach 循环。它还检查密码是否已成功更改。如果成功,则将数据输入到另一个 Datagridview。

foreach (DataGridViewRow row in dgvData.Rows)
        {
            if (!row.IsNewRow && row.Cells["cIPAddress"].Value.ToString().Contains("Invalid") == false)
            {
                if (pspasswrd(row.Cells["cIPAddress"].Value.ToString(), tbTargetUser.Text, NewPassword).Contains("Password successfully changed"))
                {
                    dgvResults.Rows.Add(row.Cells["cIPAddress"].Value.ToString(), tbTargetUser.Text, NewPassword);
                    AppendNumber = AppendNumber + IncreaseNumber;
                    NewPassword = BasePassword + AppendNumber;
                }
                else
                    row.DefaultCellStyle.BackColor = Color.Red;
            }
            Thread.Sleep(1000);
        }

但我不确定的是,如果我将下面的代码更改为使用 process.exited。它如何将密码更改与它成功使用的计算机相关联。因为它将是异步的。

public string pspasswrd(string ip, string user, string password)
    {
        String CD = @Directory.GetCurrentDirectory() + "\pspasswrd.exe";
        ProcessStartInfo p = new ProcessStartInfo();
        string result = null;
        p.FileName = CD;
        p.Arguments = @"\" + ip + " " + user + " " + password + " -accepteula";
        p.CreateNoWindow = true;
        p.RedirectStandardOutput = true;
        p.RedirectStandardError = true;
        p.UseShellExecute = false;
        Process x = Process.Start(p);
        StreamReader stream = x.StandardOutput;
        result = stream.ReadToEnd();
        x.WaitForExit(2000);
        x.Close();
        return result;
    }

您应该首先从集合中的 DataGridView 收集所有需要的信息,然后运行您的代码用于在集合而不是 DataGridView 上循环的后台线程中执行 pspasswrd.exe 并使用 WaitForExit,这将不阻止你的 UI 线程。

编辑

这是带有 WaitForExit 和新线程的代码。我相信使用 Exit 事件而不是 WaitForExit 不会有太多收获,除了更复杂和死锁的情况:

 private void OnSomeUIEvent()
    {
        //In UI thread
        var ipRows = new Dictionary<string, DataGridViewRow>();
        var targetUser = ""; //tbTargetUser.Text
        var pwd = ""; //NewPassword
        var basePassword = ""; //Some value

        foreach (DataGridViewRow row in dgvData.Rows)
        {
            var ipAddress = row.Cells["cIPAddress"].Value.ToString();

            if (!row.IsNewRow && ipAddress.Contains("Invalid") == false)
            {
                ipRows.Add(ipAddress, row);
            }
        }

        Task.Factory.StartNew(() => {

            ChangePassword(ipRows, targetUser, pwd, basePassword);

        }).ContinueWith(t => { 

           //Do Something when task completed

        });
    }

    private void ChangePassword(Dictionary<string, DataGridViewRow> ipRows, string targetUser, string newPwd, string basePwd)
    {  //in background thread
        foreach (var ipRow in ipRows)
        {
            var pwd = newPwd;
            var basePassword = basePwd;
            var appendNumber = 0;
            var increaseNumber = 1; //some number

            if (pspasswrd(ipRow.Key, targetUser, pwd).Contains("Password successfully changed"))
            {
                dgvResults.Invoke((MethodInvoker)(() =>
                {
                    dgvResults.Rows.Add(ipRow.Key, targetUser, pwd);
                }));

                appendNumber = appendNumber + increaseNumber;
                pwd = basePassword + increaseNumber;
            }
            else
            {
                dgvData.Invoke((MethodInvoker)(() =>
                {
                    ipRow.Value.DefaultCellStyle.BackColor = Color.Red;
                }));
            }
        }
    }