Как я могу проверить, получил ли процесс вывод? - PullRequest
1 голос
/ 02 марта 2011

есть способ указать, получил ли вывод, такой как стандартный калькулятор, или нет,
мне это нужно, потому что у меня есть эта строка:

sr = p1.StandardOutput;  

, и мне нужно сделать это:

s = sr.ReadLine();  

только если в калькуляторе есть вывод p1, например, нет вывода, поэтому программа застряла после ReadLine.
спасибо всем.

код:

while (i < asProcesses.Length - 1)
            {
                if ((i + 1) == asProcesses.Length - 1 && sOutRedirect != "")
                    break;
                p1.StartInfo.RedirectStandardOutput = true;
                p1.StartInfo.FileName = asProcesses[i];
                p1.StartInfo.UseShellExecute = false;
                if(i==0)
                    p1.Start();
                sr = p1.StandardOutput;
                Process p2 = new Process();
                p2.StartInfo.RedirectStandardInput = true;
                p2.StartInfo.FileName = asProcesses[i + 1];
                p2.StartInfo.UseShellExecute = false;
                p2.Start();
                sw = p2.StandardInput;
                while (!sr.EndOfStream && s != null)
                {
                    s = sr.ReadLine();
                    if (s != null)
                    {
                        sw.WriteLine(s);
                    }
                }
                if (sw != null)
                    sw.Close();
                if (sr != null)
                    sr.Close();
                i++;
            }

Ответы [ 2 ]

0 голосов
/ 02 марта 2011

Если все процессы завершаются после выполнения, используйте это вместо внутреннего while:

p1.WaitForExit();
sw.Write(sr.ReadToEnd());

Если вы хотите, чтобы время процессов истекло:

int i = 0;
while (!p1.HasExited && i < maxWaits)
{
    Thread.Sleep(delay);
    i++;
}
sw.Write(sr.ReadToEnd());

//Kill process if running:
if (!p1.HasExited)
{
    try { p1.Kill(); }
    catch { }
}

Edit:

Кажется, вы пытаетесь связать вывод каждого процесса со следующим. Если это так, вы пропускаете p1 = p2 в конце цикла.
Также рассмотрите возможность вывести первый процесс запуска из цикла: это сделает ваш код намного более читабельным. Установка p1 StartInfo должна быть перемещена в блок if (i == 0), если вы оставите его таким образом. По моему мнению, перемещение вывода для чтения из последнего процесса также не будет плохой идеей ...

Edit:

Это мое решение (с тайм-аутом):

        int maxWaits = 10; // Wait 1 second at most.
        int delay = 100;

        var p = new Process();
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.FileName = asProcesses[0];
        p.StartInfo.UseShellExecute = false;
        p.Start();

        foreach (var path in asProcesses.Skip(1))
        {
            var p2 = new Process();
            p2.StartInfo.FileName = path;
            p2.StartInfo.RedirectStandardInput = true;
            p2.StartInfo.RedirectStandardOutput = true;
            p2.StartInfo.UseShellExecute = false;

            {
                int i = 0;
                while (!p.HasExited && i < maxWaits)
                {
                    p2.StandardInput.Write(p.StandardOutput.ReadToEnd()); //Redirect IO. This line means that the second process can start calculations if the first is long-running and writes its output progressively.
                    Thread.Sleep(delay);
                    i++;
                }
            }

            p2.StandardInput.Write(p.StandardOutput.ReadToEnd()); //Redirect last output from p.

            {
                //Kill process if still running:
                if (!p.HasExited)
                {
                    try { p.Kill(); }
                    catch { }
                }
            }
        }

        {
            int i = 0;
            while (!p.HasExited && i < maxWaits)
            {
                Thread.Sleep(delay);
                i++;
            }
        }

        string result = p.StandardOutput.ReadToEnd();
        {
            if (!p.HasExited)
            {
                try { p.Kill(); }
                catch { }
            }
        }

Edit:

Алгоритм, ожидающий завершения каждого процесса:

        var p = new Process();
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.FileName = asProcesses[0];
        p.StartInfo.UseShellExecute = false;
        p.Start();

        foreach (var path in asProcesses.Skip(1))
        {
            var p2 = new Process();
            p2.StartInfo.FileName = path;
            p2.StartInfo.RedirectStandardInput = true;
            p2.StartInfo.RedirectStandardOutput = true;
            p2.StartInfo.UseShellExecute = false;

            p.WaitForExit();
            p2.StandardInput.Write(p.StandardOutput.ReadToEnd());
        }

        p.WaitForExit();
        string result = p.StandardOutput.ReadToEnd();

Я переместил первый процесс из цикла, чтобы избавиться от условного. Таким образом, поток управления проще и проще добавить привязанность кода к первому процессу.

0 голосов
/ 02 марта 2011
void foo()
{
    System.Diagnostics.Process p = new System.Diagnostics.Process();
    p.StartInfo.FileName = "c:\\windows\\system32\\ping.exe";
    p.StartInfo.RedirectStandardOutput = true;
    p.StartInfo.UseShellExecute = false;
    p.EnableRaisingEvents = true;
    p.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(p_OutputDataReceived);
    p.Start();
    p.BeginOutputReadLine();
}           

void p_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
{
    string s = e.Data;        
    // process s
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...