IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Problème lorsqu'il y a Process standardOutput.ReadToEnd()


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 284
    Points : 79
    Points
    79
    Par défaut Problème lorsqu'il y a Process standardOutput.ReadToEnd()
    Bonjour,

    Je réalise actuellement un programme console en C#.
    Je dois lancer des ".bat" via cet utilitaire. Ces ".bat" sont des boîtes noirs, je ne peux absolument pas les modifier.

    j'ai donc mon code qui ressemble à ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    System.Diagnostics.Process proc = new System.Diagnostics.Process();
    proc.StartInfo.FileName = "cmd";
    proc.StartInfo.CreateNoWindow = false;
     
    proc.StartInfo.RedirectStandardInput = true;
    proc.StartInfo.RedirectStandardError = true;
    proc.StartInfo.RedirectStandardOutput = true;
    proc.StartInfo.UseShellExecute = false;
    proc.Start();
     
    proc.StandardInput.WriteLine("cd /d " + directoryBat);
    proc.StandardInput.WriteLine(batFilename);              
    proc.StandardInput.Close();
     
    consoleContentOutput = proc.StandardOutput.ReadToEnd();
    consoleContentError = proc.StandardError.ReadToEnd();
    proc.WaitForExit();
    finalExitCode = proc.ExitCode;
    return finalExitCode;
    En fait, je viens de faire le test avec deux ".bat".
    Avec un je n'ai aucun soucis. Avec l'autre, ça ne s'arrête jamais, comme si l'éxécution était sur pause.
    Quand je retire cette ligne, l'éxécution se termine bien:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    consoleContentOutput = proc.StandardOutput.ReadToEnd();
    Je ne sais absolument pas d'où ça peut venir.
    Est ce que quelqu'un aurait une idée?

    Pour info: les ".bat" lancent des ".JAR".
    Par avance merci.

  2. #2
    Membre habitué
    Avatar de yvesall
    Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Novembre 2006
    Messages
    208
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2006
    Messages : 208
    Points : 127
    Points
    127
    Par défaut
    cela ne proviendrait-il pas du ReadToEnd() qui reste en attente puisque aucun flux n'est apparu ?

    Le code suivant est bloquant:
    proc.StandardOutput.ReadToEnd();

    il se débloque quand le flux se ferme.
    Mais dans le cas où aucun std::err n'est fait
    proc.StandardError.ReadToEnd();
    va attendre quelque chose qui ne viendra jamais.
    i = i++;

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Septembre 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2012
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Ton problème provient du fait que tu rediriges les deux sorties standards (Output et Error) et que tu les lis à l'aide de proc.StandardOutput.ReadToEnd et proc.StandardError.ReadToEnd.

    Le processus lancé (proc.Start()) remplit le ou les buffer et attend qu'ils soient vidés pour continuer. Le problème est que ReadToEnd (le premier des deux par exemple) attend aussi que le processus soit terminé pour rendre la main.
    Le premier ReadToEnd est donc en cours, attend que le processus se termine, qui lui attend probablement l'appel du second ReadToEnd pour vider le second buffer -> DeadLock.

    La solution : mettre en place une lecture asynchrone des flux de sortie.
    (désolé pour la réponse en VB mais c'est la seule que j'ai sous la main)


    proc.StartInfo.RedirectStandardOutput = True
    proc.StartInfo.RedirectStandardError = True

    ' Set event handler to asynchronously read the output.
    AddHandler proc.OutputDataReceived, AddressOf MyOutputHandler
    ' Set event handler to asynchronously read the error.
    AddHandler proc.ErrorDataReceived, AddressOf MyErrorHandler


    avec les gestionnaires définis de la façon suivante par exemple :


    Private Sub MyOutputHandler(ByVal sendingProcess As Object, ByVal outLine As DataReceivedEventArgs)

    ' Collect the sort command output.
    If Not String.IsNullOrEmpty(outLine.Data) Then

    ' Add the text to the collected output.
    myOutput.Append(outLine.Data)
    End If
    End Sub

    Private Sub MyErrorHandler(ByVal sendingProcess As Object, ByVal outLine As DataReceivedEventArgs)

    ' Collect the sort command output.
    If Not String.IsNullOrEmpty(outLine.Data) Then

    ' Add the text to the collected output.
    myError.Append(outLine.Data)
    End If
    End Sub

    où myOutput et myError auront été déclarés comme des StringBuilder au niveau du module (si les messages d'erreurs t'intéressent).

    Le lancement de ton process s'effectue donc de la façon suivante :

    proc.Start()
    proc.BeginOutputReadLine()
    proc.BeginErrorReadLine()

    proc.WaitForExit()

    proc.Dispose()

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 284
    Points : 79
    Points
    79
    Par défaut
    Merc pour ces réponses.
    Je vais donc regarder du côté de la lecture asynchrone.
    Merci pour le code, même si c'esten VB, c'es mieux que rien.
    Je reviens vers vous dès que j'ai fait le test pour voir si ça fonctionne mieux. En tout cas merci pour ces pistes.

Discussions similaires

  1. Problème lorsque je veux changer une session
    Par mouloudéen dans le forum Windows XP
    Réponses: 3
    Dernier message: 16/12/2006, 13h51
  2. Problème lorsque je créais de module.
    Par Sh1v3r dans le forum Langage
    Réponses: 8
    Dernier message: 24/07/2006, 14h58
  3. Probléme lorsqu'une fenétre passe par dessus l'autre...
    Par hostile dans le forum Interfaces Graphiques en Java
    Réponses: 4
    Dernier message: 03/01/2006, 19h20
  4. [C#] Comment décoder le Diagnostics.Process.StandardOutput
    Par CrashMan dans le forum Contribuez
    Réponses: 14
    Dernier message: 11/07/2005, 11h10
  5. [DirectShow] problème lorsque je détruit mon graphe
    Par juldjin2 dans le forum DirectX
    Réponses: 1
    Dernier message: 04/02/2004, 21h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo