ProcessStartInfo accroché à "WaitForExit"? Pourquoi?

j'ai le code suivant:

info = new System.Diagnostics.ProcessStartInfo("TheProgram.exe", String.Join(" ", args));
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(info);
p.WaitForExit();
Console.WriteLine(p.StandardOutput.ReadToEnd()); //need the StandardOutput contents

je sais que la sortie du processus que je démarre est d'environ 7 Mo de long. L'exécuter dans la console Windows fonctionne très bien. Malheureusement programmatically cela pend indéfiniment à WaitForExit. Notez aussi que cela ne Code pas hang pour les sorties plus petites (comme 3KB).

est-il possible que la sortie standard interne de ProcessStartInfo ne puisse pas amortir 7MB? Si oui, que devrais-je faire à la place? Si ce n', ce que je fais mal?

156
demandé sur Kara 2008-09-26 17:46:56

17 réponses

le problème est que si vous redirigez StandardOutput et/ou StandardError le tampon interne peut devenir plein. Quel que soit l'ordre que vous utilisez, il peut y avoir un problème:

  • si vous attendez que le processus se termine avant de lire StandardOutput le processus peut bloquer en essayant de lui écrire, de sorte que le processus ne se termine jamais.
  • si vous lisez à partir de StandardOutput en utilisant ReadToEnd alors votre "processus 1519160920" peut bloquer si le processus ne ferme jamais StandardOutput (par exemple si elle ne se termine jamais, ou si elle est bloquée en écriture à StandardError ).

la solution consiste à utiliser des lectures asynchrones pour s'assurer que le tampon ne se remplit pas. Pour éviter les blocages et collecter toutes les sorties de StandardOutput et StandardError vous pouvez faire ceci:

Modifier: voir les réponses ci-dessous pour savoir comment éviter un ObjectDisposedException si le délai se produit.

using (Process process = new Process())
{
    process.StartInfo.FileName = filename;
    process.StartInfo.Arguments = arguments;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;

    StringBuilder output = new StringBuilder();
    StringBuilder error = new StringBuilder();

    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
    using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
    {
        process.OutputDataReceived += (sender, e) => {
            if (e.Data == null)
            {
                outputWaitHandle.Set();
            }
            else
            {
                output.AppendLine(e.Data);
            }
        };
        process.ErrorDataReceived += (sender, e) =>
        {
            if (e.Data == null)
            {
                errorWaitHandle.Set();
            }
            else
            {
                error.AppendLine(e.Data);
            }
        };

        process.Start();

        process.BeginOutputReadLine();
        process.BeginErrorReadLine();

        if (process.WaitForExit(timeout) &&
            outputWaitHandle.WaitOne(timeout) &&
            errorWaitHandle.WaitOne(timeout))
        {
            // Process completed. Check process.ExitCode here.
        }
        else
        {
            // Timed out.
        }
    }
}
328
répondu Mark Byers 2017-07-24 14:57:59

le documentation pour Process.StandardOutput dit de lire avant d'attendre autrement vous pouvez deadlock, snippet copié ci-dessous:

 // Start the child process.
 Process p = new Process();
 // Redirect the output stream of the child process.
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "Write500Lines.exe";
 p.Start();
 // Do not wait for the child process to exit before
 // reading to the end of its redirected stream.
 // p.WaitForExit();
 // Read the output stream first and then wait.
 string output = p.StandardOutput.ReadToEnd();
 p.WaitForExit();
83
répondu Rob 2011-01-14 15:22:09

Marque Byers réponse est excellente, mais je voudrais juste ajouter les éléments suivants: la OutputDataReceived et ErrorDataReceived délégués doivent être supprimés avant la outputWaitHandle et errorWaitHandle sont disposées. Si le processus continue à produire des données après que le délai d'attente a été dépassé et se termine, les variables outputWaitHandle et errorWaitHandle seront accessibles après élimination.

(pour information j'ai dû ajouter cette mise en garde comme réponse car je ne pouvais pas commenter sur son post.)

17
répondu stevejay 2012-04-10 10:29:14

le problème avec l'Exception unhandled Objectdisposed se produit lorsque le processus est chronométré. Dans ce cas, les autres parties de la condition:

if (process.WaitForExit(timeout) 
    && outputWaitHandle.WaitOne(timeout) 
    && errorWaitHandle.WaitOne(timeout))

ne sont pas exécutés. J'ai résolu ce problème de la manière suivante:

using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
{
    using (process = new Process())
    {
        // preparing ProcessStartInfo

        try
        {
            process.OutputDataReceived += (sender, e) =>
                {
                    if (e.Data == null)
                    {
                        outputWaitHandle.Set();
                    }
                    else
                    {
                        outputBuilder.AppendLine(e.Data);
                    }
                };
            process.ErrorDataReceived += (sender, e) =>
                {
                    if (e.Data == null)
                    {
                        errorWaitHandle.Set();
                    }
                    else
                    {
                        outputBuilder.AppendLine(e.Data);
                    }
                };

            process.Start();

            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            if (process.WaitForExit(timeout))
            {
                exitCode = process.ExitCode;
            }
            else
            {
                // timed out
            }

            output = outputBuilder.ToString();
        }
        finally
        {
            outputWaitHandle.WaitOne(timeout);
            errorWaitHandle.WaitOne(timeout);
        }
    }
}
15
répondu Karol Tyl 2014-04-10 22:28:37

Rob répondit et me sauva quelques heures de plus d'épreuves. Lire le tampon de sortie / erreur avant d'attendre:

// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
7
répondu Jon 2016-01-08 22:39:33

nous avons aussi cette question (ou une variante).

essayez ce qui suit:

1) Ajouter un délai à la P. WaitForExit (nnnn); où nnnn est en millisecondes.

2) Mettez l'appel ReadToEnd avant L'appel WaitForExit. Ce est ce que nous avons vu MS recommande.

5
répondu torial 2008-09-26 13:57:19

il s'agit d'une solution awaitable plus moderne, basée sur une bibliothèque parallèle de tâches (TPL) pour .NET 4.5 et au-dessus.

Exemple D'Utilisation

try
{
    var exitCode = await StartProcess(
        "dotnet", 
        "--version", 
        @"C:\",
        10000, 
        Console.Out, 
        Console.Out);
    Console.WriteLine($"Process Exited with Exit Code {exitCode}!");
}
catch (TaskCanceledException)
{
    Console.WriteLine("Process Timed Out!");
}

mise en œuvre

public static async Task<int> StartProcess(
    string filename,
    string arguments,
    string workingDirectory= null,
    int? timeout = null,
    TextWriter outputTextWriter = null,
    TextWriter errorTextWriter = null)
{
    using (var process = new Process()
    {
        StartInfo = new ProcessStartInfo()
        {
            CreateNoWindow = true,
            Arguments = arguments,
            FileName = filename,
            RedirectStandardOutput = outputTextWriter != null,
            RedirectStandardError = errorTextWriter != null,
            UseShellExecute = false,
            WorkingDirectory = workingDirectory
        }
    })
    {
        process.Start();
        var cancellationTokenSource = timeout.HasValue ?
            new CancellationTokenSource(timeout.Value) :
            new CancellationTokenSource();

        var tasks = new List<Task>(3) { process.WaitForExitAsync(cancellationTokenSource.Token) };
        if (outputTextWriter != null)
        {
            tasks.Add(ReadAsync(
                x =>
                {
                    process.OutputDataReceived += x;
                    process.BeginOutputReadLine();
                },
                x => process.OutputDataReceived -= x,
                outputTextWriter,
                cancellationTokenSource.Token));
        }

        if (errorTextWriter != null)
        {
            tasks.Add(ReadAsync(
                x =>
                {
                    process.ErrorDataReceived += x;
                    process.BeginErrorReadLine();
                },
                x => process.ErrorDataReceived -= x,
                errorTextWriter,
                cancellationTokenSource.Token));
        }

        await Task.WhenAll(tasks);
        return process.ExitCode;
    }
}

/// <summary>
/// Waits asynchronously for the process to exit.
/// </summary>
/// <param name="process">The process to wait for cancellation.</param>
/// <param name="cancellationToken">A cancellation token. If invoked, the task will return
/// immediately as cancelled.</param>
/// <returns>A Task representing waiting for the process to end.</returns>
public static Task WaitForExitAsync(
    this Process process,
    CancellationToken cancellationToken = default(CancellationToken))
{
    process.EnableRaisingEvents = true;

    var taskCompletionSource = new TaskCompletionSource<object>();

    EventHandler handler = null;
    handler = (sender, args) =>
    {
        process.Exited -= handler;
        taskCompletionSource.TrySetResult(null);
    };
    process.Exited += handler;

    if (cancellationToken != default(CancellationToken))
    {
        cancellationToken.Register(
            () =>
            {
                process.Exited -= handler;
                taskCompletionSource.TrySetCanceled();
            });
    }

    return taskCompletionSource.Task;
}

/// <summary>
/// Reads the data from the specified data recieved event and writes it to the
/// <paramref name="textWriter"/>.
/// </summary>
/// <param name="addHandler">Adds the event handler.</param>
/// <param name="removeHandler">Removes the event handler.</param>
/// <param name="textWriter">The text writer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public static Task ReadAsync(
    this Action<DataReceivedEventHandler> addHandler,
    Action<DataReceivedEventHandler> removeHandler,
    TextWriter textWriter,
    CancellationToken cancellationToken = default(CancellationToken))
{
    var taskCompletionSource = new TaskCompletionSource<object>();

    DataReceivedEventHandler handler = null;
    handler = new DataReceivedEventHandler(
        (sender, e) =>
        {
            if (e.Data == null)
            {
                removeHandler(handler);
                taskCompletionSource.TrySetResult(null);
            }
            else
            {
                textWriter.WriteLine(e.Data);
            }
        });

    addHandler(handler);

    if (cancellationToken != default(CancellationToken))
    {
        cancellationToken.Register(
            () =>
            {
                removeHandler(handler);
                taskCompletionSource.TrySetCanceled();
            });
    }

    return taskCompletionSource.Task;
}
5
répondu Muhammad Rehan Saeed 2016-10-08 06:24:22

crédit à EM0 pour https://stackoverflow.com/a/17600012/4151626

les autres solutions (y compris EM0's) toujours bloquées pour mon application, en raison des délais internes et de l'utilisation de la production standard et StandardError par l'application générée. Voici ce qui a fonctionné pour moi:

Process p = new Process()
{
  StartInfo = new ProcessStartInfo()
  {
    FileName = exe,
    Arguments = args,
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true
  }
};
p.Start();

string cv_error = null;
Thread et = new Thread(() => { cv_error = p.StandardError.ReadToEnd(); });
et.Start();

string cv_out = null;
Thread ot = new Thread(() => { cv_out = p.StandardOutput.ReadToEnd(); });
ot.Start();

p.WaitForExit();
ot.Join();
et.Join();

Edit: ajout de L'initialisation de StartInfo à l'exemple de code

2
répondu ergohack 2017-12-16 00:22:09

Je l'ai résolu de cette façon:

            Process proc = new Process();
            proc.StartInfo.FileName = batchFile;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.RedirectStandardInput = true;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;      
            proc.Start();
            StreamWriter streamWriter = proc.StandardInput;
            StreamReader outputReader = proc.StandardOutput;
            StreamReader errorReader = proc.StandardError;
            while (!outputReader.EndOfStream)
            {
                string text = outputReader.ReadLine();                    
                streamWriter.WriteLine(text);
            }

            while (!errorReader.EndOfStream)
            {                   
                string text = errorReader.ReadLine();
                streamWriter.WriteLine(text);
            }

            streamWriter.Close();
            proc.WaitForExit();

j'ai redirigé à la fois l'entrée, la sortie et l'erreur et j'ai traité la lecture des flux de sortie et d'erreur. Cette solution fonctionne pour SDK 7-8.1, à la fois pour Windows 7 et Windows 8

1
répondu Elina Maliarsky 2015-09-08 11:53:23

j'ai essayé de faire un cours qui résoudrait votre problème en utilisant le flux asynchrone lire, en prenant en compte Mark Byers, Rob, stevejay réponses. Ce faisant, j'ai réalisé qu'il y avait un bug lié à la lecture asynchrone du flux de sortie du processus.

j'ai signalé ce bug chez Microsoft: https://connect.microsoft.com/VisualStudio/feedback/details/3119134

résumé:

vous ne pouvez pas faire que:

process.BeginOutputReadLine (); process.Start ();

vous recevrez le système.InvalidOperationException: StandardOut a pas été réexpédiés ou le processus n'a pas encore commencé.

============================================================================================================================

alors vous devez démarrer la sortie asynchrone lire après le processus est commencé:

process.Start (); process.BeginOutputReadLine ();

faire ainsi, faire une condition de course parce que le flux de sortie peut recevoir les données avant de vous le mettre en asynchrone:

process.Start(); 
// Here the operating system could give the cpu to another thread.  
// For example, the newly created thread (Process) and it could start writing to the output
// immediately before next line would execute. 
// That create a race condition.
process.BeginOutputReadLine();

============================================================================================================================

alors certains pourraient dire que vous suffit de lire le flux avant de le régler sur asynchrone. Mais le même problème se produit. Y sera une condition de course entre la lecture synchrone et flux en mode asynchrone.

============================================================================================================================

il n'y a aucun moyen d'obtenir une lecture asynchrone sûre d'un flux de sortie d'un processus dans la "Process" et" ProcessStartInfo " ont été conçu.

vous êtes probablement mieux utiliser asynchrone lire comme suggéré par d'autres utilisateurs pour votre cas. Mais vous devez être conscient que vous pourriez manquer certaines informations en raison de l'état de la course.

1
répondu Eric Ouellet 2017-01-19 16:49:51

aucune des réponses ci-dessus ne fait le travail.

Rob solution se bloque et 'A' obtenir la solution disposé d'exception.(J'ai essayé les "solutions" des autres réponses).

J'ai donc décidé de proposer une autre solution:

public void GetProcessOutputWithTimeout(Process process, int timeoutSec, CancellationToken token, out string output, out int exitCode)
{
    string outputLocal = "";  int localExitCode = -1;
    var task = System.Threading.Tasks.Task.Factory.StartNew(() =>
    {
        outputLocal = process.StandardOutput.ReadToEnd();
        process.WaitForExit();
        localExitCode = process.ExitCode;
    }, token);

    if (task.Wait(timeoutSec, token))
    {
        output = outputLocal;
        exitCode = localExitCode;
    }
    else
    {
        exitCode = -1;
        output = "";
    }
}

using (var process = new Process())
{
    process.StartInfo = ...;
    process.Start();
    string outputUnicode; int exitCode;
    GetProcessOutputWithTimeout(process, PROCESS_TIMEOUT, out outputUnicode, out exitCode);
}

ce code a été débogué et fonctionne parfaitement.

1
répondu omriman12 2017-02-09 15:32:50

Introduction

réponse actuellement acceptée ne fonctionne pas (sauf pour les lancers) et il y a trop de solutions de rechange mais pas de code complet. Cela fait évidemment perdre beaucoup de temps aux gens parce que c'est une question populaire.

combinant la réponse de Mark Byers et la réponse de Karol Tyl j'ai écrit le code complet basé sur la façon dont je veux utiliser le processus.Méthode de démarrage.

Utilisation

je l'ai utilisé pour créer progrès dialogue autour des commandes git. Voici comment je l'ai utilisé:

    private bool Run(string fullCommand)
    {
        Error = "";
        int timeout = 5000;

        var result = ProcessNoBS.Start(
            filename: @"C:\Program Files\Git\cmd\git.exe",
            arguments: fullCommand,
            timeoutInMs: timeout,
            workingDir: @"C:\test");

        if (result.hasTimedOut)
        {
            Error = String.Format("Timeout ({0} sec)", timeout/1000);
            return false;
        }

        if (result.ExitCode != 0)
        {
            Error = (String.IsNullOrWhiteSpace(result.stderr)) 
                ? result.stdout : result.stderr;
            return false;
        }

        return true;
    }

en théorie, vous pouvez aussi combiner stdout et stderr, mais je ne l'ai pas testé.

Code

public struct ProcessResult
{
    public string stdout;
    public string stderr;
    public bool hasTimedOut;
    private int? exitCode;

    public ProcessResult(bool hasTimedOut = true)
    {
        this.hasTimedOut = hasTimedOut;
        stdout = null;
        stderr = null;
        exitCode = null;
    }

    public int ExitCode
    {
        get 
        {
            if (hasTimedOut)
                throw new InvalidOperationException(
                    "There was no exit code - process has timed out.");

            return (int)exitCode;
        }
        set
        {
            exitCode = value;
        }
    }
}

public class ProcessNoBS
{
    public static ProcessResult Start(string filename, string arguments,
        string workingDir = null, int timeoutInMs = 5000,
        bool combineStdoutAndStderr = false)
    {
        using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
        using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
        {
            using (var process = new Process())
            {
                var info = new ProcessStartInfo();

                info.CreateNoWindow = true;
                info.FileName = filename;
                info.Arguments = arguments;
                info.UseShellExecute = false;
                info.RedirectStandardOutput = true;
                info.RedirectStandardError = true;

                if (workingDir != null)
                    info.WorkingDirectory = workingDir;

                process.StartInfo = info;

                StringBuilder stdout = new StringBuilder();
                StringBuilder stderr = combineStdoutAndStderr
                    ? stdout : new StringBuilder();

                var result = new ProcessResult();

                try
                {
                    process.OutputDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                            outputWaitHandle.Set();
                        else
                            stdout.AppendLine(e.Data);
                    };
                    process.ErrorDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                            errorWaitHandle.Set();
                        else
                            stderr.AppendLine(e.Data);
                    };

                    process.Start();

                    process.BeginOutputReadLine();
                    process.BeginErrorReadLine();

                    if (process.WaitForExit(timeoutInMs))
                        result.ExitCode = process.ExitCode;
                    // else process has timed out 
                    // but that's already default ProcessResult

                    result.stdout = stdout.ToString();
                    if (combineStdoutAndStderr)
                        result.stderr = null;
                    else
                        result.stderr = stderr.ToString();

                    return result;
                }
                finally
                {
                    outputWaitHandle.WaitOne(timeoutInMs);
                    errorWaitHandle.WaitOne(timeoutInMs);
                }
            }
        }
    }
}
1
répondu Marko Avlijaš 2017-04-04 15:31:01

je sais que c'est vieux mais, après avoir lu toute cette page aucune des solutions ne fonctionnait pour moi, bien que je n'ai pas essayé Muhammad Rehan car le code était un peu difficile à suivre, bien que je suppose qu'il était sur la bonne voie. Quand je dis que ça n'a pas fonctionné, ce n'est pas tout à fait vrai, parfois ça marchait bien, je suppose que ça a quelque chose à voir avec la longueur de la sortie avant une marque EOF.

quoi qu'il en soit, la solution qui a fonctionné pour moi était d'utiliser différents les threads de lire le StandardOutput et StandardError et écrire les messages.

        StreamWriter sw = null;
        var queue = new ConcurrentQueue<string>();

        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);
            }
        }
    }

Espérons que cela aide quelqu'un, qui pensaient que cela pourrait être si dur!

1
répondu Alexis Coles 2017-06-08 07:02:16

après avoir lu tous les billets ici, je me suis décidé sur la solution consolidée de Marko Avlijaš. cependant , il n'a pas résolu tous mes problèmes.

dans notre environnement, nous avons un service Windows qui est prévu pour fonctionner des centaines de différentes .chauve. cmd .EXE.,.. etc. des dossiers qui se sont accumulés au fil des ans et qui ont été rédigés par de nombreuses personnes et dans des styles différents. Nous n'avons aucun contrôle sur l'écriture des programmes et des scripts, nous sont simplement responsables de l'ordonnancement, de l'exécution et des rapports sur le succès/l'échec.

Alors j'ai essayé à peu près toutes les suggestions ici avec différents niveaux de succès. La réponse de Marko était presque parfaite, mais lorsqu'elle était exécutée en tant que service, elle ne saisissait pas toujours stdout. Je n'ai jamais pu le bas de la pourquoi pas.

la seule solution que nous avons trouvé qui fonctionne dans tous nos cas est celle-ci: http://csharptest.net/319/using-the-processrunner-class/index.html

1
répondu flapster 2018-02-01 14:19:04

ce post peut-être périmé, mais j'ai découvert la cause principale pourquoi il est généralement hang est due à débordement de la pile pour le redirectStandardoutput ou si vous avez redirectStandarderror.

comme les données de sortie ou les données d'erreur sont grandes, il causera un temps mort car il est encore en traitement pour une durée indéterminée.

donc, pour résoudre ce problème:

p.StartInfo.RedirectStandardoutput = False
p.StartInfo.RedirectStandarderror = False
0
répondu song 2011-08-31 00:42:22

je pense que c'est simple et la meilleure approche (nous n'avons pas besoin AutoResetEvent ):

public static string GGSCIShell(string Path, string Command)
{
    using (Process process = new Process())
    {
        process.StartInfo.WorkingDirectory = Path;
        process.StartInfo.FileName = Path + @"\ggsci.exe";
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.UseShellExecute = false;

        StringBuilder output = new StringBuilder();
        process.OutputDataReceived += (sender, e) =>
        {
            if (e.Data != null)
            {
                output.AppendLine(e.Data);
            }
        };

        process.Start();
        process.StandardInput.WriteLine(Command);
        process.BeginOutputReadLine();


        int timeoutParts = 10;
        int timeoutPart = (int)TIMEOUT / timeoutParts;
        do
        {
            Thread.Sleep(500);//sometimes halv scond is enough to empty output buff (therefore "exit" will be accepted without "timeoutPart" waiting)
            process.StandardInput.WriteLine("exit");
            timeoutParts--;
        }
        while (!process.WaitForExit(timeoutPart) && timeoutParts > 0);

        if (timeoutParts <= 0)
        {
            output.AppendLine("------ GGSCIShell TIMEOUT: " + TIMEOUT + "ms ------");
        }

        string result = output.ToString();
        return result;
    }
}
0
répondu Kuzman Marinov 2012-10-20 16:00:39

j'avais le même problème, mais la raison était différente. Cela se produirait cependant sous Windows 8, mais pas sous Windows 7. La ligne suivante semble avoir causé le problème.

pProcess.StartInfo.UseShellExecute = False

la solution était de ne pas désactiver Useshellexécute. J'ai maintenant reçu une fenêtre popup Shell, qui est indésirable, mais beaucoup mieux que le programme attendant rien de particulier à se produire. J'ai donc ajouté les travaux suivants pour cela:

pProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden

maintenant, la seule chose qui me dérange est de savoir pourquoi cela se passe sous Windows 8.

-1
répondu ohgodnotanotherone 2015-01-13 10:35:39