.NET Обработка проблем с порождением - PullRequest
6 голосов
/ 16 декабря 2008

У меня есть исполняемый файл, который запускается мгновенно из командной строки, но, по-видимому, никогда не возвращается при порождении с использованием System.Diagnostics.Process:

В основном я пишу оболочку библиотеки .NET вокруг интерфейса CLI Accurev, поэтому каждый вызов метода порождает процесс CLI для выполнения команды.

Это прекрасно работает для всех, кроме одной команды:

  accurev.exe show depots

Тем не менее, при запуске этого из консоли, он работает нормально, когда я вызываю его с помощью процесса .net, он зависает ... Код запуска процесса, который я использую:

    public static string ExecuteCommand(string command)
    {

        Process p = createProcess(command);

        p.Start();            
        p.WaitForExit();

        // Accurev writes to the error stream if ExitCode is non zero.
        if (p.ExitCode != 0)
        {
            string error = p.StandardError.ReadToEnd();
            Log.Write(command + " failed..." + error);
            throw new AccurevException(error);                 
        }
        else
        {
            return p.StandardOutput.ReadToEnd();
        }

    }

    /// Creates Accurev Process 
    /// </summary>
    /// <param name="command"></param>
    /// <returns></returns>
    private static Process createProcess(string command)
    {
        Log.Write("Executing Command: " + command);

        ProcessStartInfo startInfo = new ProcessStartInfo();
        Process p = new Process();

        startInfo.CreateNoWindow = false;
        startInfo.RedirectStandardOutput = true;
        startInfo.RedirectStandardInput = true;
        startInfo.RedirectStandardError = true;

        startInfo.UseShellExecute = false;
        startInfo.Arguments = command;
        startInfo.FileName = _accurev;

        p.StartInfo = startInfo;

        return p;
    }

Висит в p.WaitForExit ().

Любой совет?

РЕДАКТИРОВАТЬ : Решено!

.NET зависание процесса, если выходной буфер переполняется, я переключился на использование метода асинхронного чтения, и все работает:

    public static string ExecuteCommand(string command)
    {
        StringBuilder outputData = new StringBuilder();

        Process p = createProcess(command);

        p.OutputDataReceived += delegate(object sender, DataReceivedEventArgs e)
        {
            outputData.AppendLine(e.Data);
        };

        p.Start();
        p.BeginOutputReadLine();

        p.WaitForExit();

        // Accurev writes to the error stream if ExitCode is non zero.
        if (p.ExitCode != 0)
        {
            string error = p.StandardError.ReadToEnd();
            Log.Write(command + " failed..." + error);
            throw new AccurevException(error);                 
        }
        else
        {
            return outputData.ToString();
        }

    }   

Ответы [ 3 ]

2 голосов
/ 16 декабря 2008

Это ищет вход? В частности, я заметил, что вы перенаправляете стандартный ввод, но не закрываете его, поэтому, если он читает со стандартного ввода, он зависнет.

1 голос
/ 16 декабря 2008

Активирован ли порожденный процесс во время выполнения WaitForExit ()? Вы можете прикрепить к нему отладчик?

0 голосов
/ 16 декабря 2008

попробуйте заменить WaitForExit () на что-то вроде этого:

while (!p.WaitForExit(100))
    Console.Write(".");

Еще одна попытка - установить для UseShellExecute значение true и наблюдать за появлением окна консоли. Смотрите эту страницу для тонкости этого параметра: http://blogs.msdn.com/jmstall/archive/2006/09/28/CreateNoWindow.aspx

...