ProcessStartInfo hanging on “WaitForExit”? Why?

前端 未结 22 1863
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 02:59

I have the following code:

info = new System.Diagnostics.ProcessStartInfo(\"TheProgram.exe\", String.Join(\" \", args));
info.CreateNoWindow = true;
info.Win         


        
22条回答
  •  孤独总比滥情好
    2020-11-22 03:08

    I know that this is supper old but, after reading this whole page none of the solutions was working for me, although I didn't try Muhammad Rehan as the code was a little hard to follow, although I guess he was on the right track. When I say it didn't work that's not entirely true, sometimes it would work fine, I guess it is something to do with the length of the output before an EOF mark.

    Anyway, the solution that worked for me was to use different threads to read the StandardOutput and StandardError and write the messages.

            StreamWriter sw = null;
            var queue = new ConcurrentQueue();
    
            var flushTask = new System.Timers.Timer(50);
            flushTask.Elapsed += (s, e) =>
            {
                while (!queue.IsEmpty)
                {
                    string line = null;
                    if (queue.TryDequeue(out line))
                        sw.WriteLine(line);
                }
                sw.FlushAsync();
            };
            flushTask.Start();
    
            using (var process = new Process())
            {
                try
                {
                    process.StartInfo.FileName = @"...";
                    process.StartInfo.Arguments = $"...";
                    process.StartInfo.UseShellExecute = false;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.StartInfo.RedirectStandardError = true;
    
                    process.Start();
    
                    var outputRead = Task.Run(() =>
                    {
                        while (!process.StandardOutput.EndOfStream)
                        {
                            queue.Enqueue(process.StandardOutput.ReadLine());
                        }
                    });
    
                    var errorRead = Task.Run(() =>
                    {
                        while (!process.StandardError.EndOfStream)
                        {
                            queue.Enqueue(process.StandardError.ReadLine());
                        }
                    });
    
                    var timeout = new TimeSpan(hours: 0, minutes: 10, seconds: 0);
    
                    if (Task.WaitAll(new[] { outputRead, errorRead }, timeout) &&
                        process.WaitForExit((int)timeout.TotalMilliseconds))
                    {
                        if (process.ExitCode != 0)
                        {
                            throw new Exception($"Failed run... blah blah");
                        }
                    }
                    else
                    {
                        throw new Exception($"process timed out after waiting {timeout}");
                    }
                }
                catch (Exception e)
                {
                    throw new Exception($"Failed to succesfully run the process.....", e);
                }
            }
        }
    

    Hope this helps someone, who thought this could be so hard!

提交回复
热议问题