0
votes

StandardOutput renvoyant une chaîne vide en C #

Des questions similaires sur STDOUT ( STandarOUTput ) ont déjà été posées. Mais dans mon cas, il n'y a pas d'exception, toujours, le résultat de sortie est une chaîne vide.

En utilisant le code suivant, je parviens à exécuter le fichier EXE. L'exe renvoie une sortie sur la fenêtre de commande, que je peux également voir. Maintenant, je veux lire cette sortie dans une chaîne. Dans le code ci-dessous, le strOutput est une chaîne vide (même si je peux voir une sortie sur la fenêtre de commande).

Voici mon code:

System.Diagnostics.Process myProcess = new System.Diagnostics.Process();

try
{
    myProcess.StartInfo.Arguments = "";
    myProcess.StartInfo.UseShellExecute = false;             
    myProcess.StartInfo.FileName = @"D:\exeFilePath\exedrivermanager.exe";
    myProcess.StartInfo.CreateNoWindow = true;         

    myProcess.StartInfo.RedirectStandardOutput = true;
    myProcess.Start();
    string strOutput = myProcess.StandardOutput.ReadToEnd(); //THIS RETURNS AN EMPTY STRING.

    Console.WriteLine(Environment.NewLine + Environment.NewLine + "Output: " + strOutput);

    //Wait for process to finish
    myProcess.WaitForExit();
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}

EDIT:

J'ai réalisé qu'il n'est pas possible d'écrire la sortie dans un fichier même avec la ligne de commande. Il semble que le programme appelé ne se termine jamais complètement. Le programme appelé quitte la ligne de commande comme indiqué dans la capture d'écran ci-dessous.


13 commentaires

Pouvez-vous faire en sorte que le processus écrive également la sortie dans un fichier et lise la sortie produite à partir de là?


Si vous voyez la sortie, c'est qu'elle n'a PAS été redirigée . En supposant que le programme appelé n'alloue pas sa propre console (ce qui pourrait être possible), vous pouvez également vérifier le flux d'erreurs


@BogdanDoicin: J'ai essayé de passer > D: \\ IntallLog.txt comme argument mais le fichier n'a pas été créé. Je ne suis pas sûr de la manière correcte d'écrire la sortie dans un fichier dans ce cas.


@skm vous modifiez d'abord le programme d'origine pour écrire la sortie dans un fichier, puis vous utilisez le deuxième programme pour lire à partir du fichier.


@BogdanDoicin: Je n'ai pas le contrôle sur le programme d'origine (le programme que j'exécute via ce programme C #). Je ne peux apporter des modifications qu'à ce prorgramme C #. * Je ne sais pas si je vous ai bien compris.


Ah, maintenant je comprends. Si vous aviez le contrôle sur le programme d'origine, je pense que la méthode des fichiers aurait été une bonne alternative.


Avez-vous essayé d'exécuter exedrivermanager à partir de la ligne de commande et voir si vous pouvez rediriger la sortie vers un fichier?


@PaulF: Maintenant, j'ai essayé d'écrire la sortie sur un fichier à partir de la ligne de commande et même cela ne fonctionne pas. Je pense que le exedrivermanager ne se ferme pas complètement. Je vois le curseur clignoter.


Si la sortie n'est pas redirigée lors de l'exécution à partir de la ligne de commande, il semblerait que la sortie ne soit pas écrite dans le flux de sortie standard. Avez-vous essayé de rediriger stderr vers un fichier "exedrivermanager 2> myfile.txt"


Une autre possibilité est que la sortie soit mise en mémoire tampon jusqu'à ce que l'application se ferme correctement.


@PaulF: Désolé, je n'ai pas compris ce que vous voulez dire. Dans l'une des réponses ci-dessous, Ali a suggéré d'utiliser RedirectStandardError mais le programme n'y entre jamais.


Avez-vous ajouté l'appel à BeginErrorReadLine comme indiqué dans la réponse d'Ilyakom


@PaulF: Oui, je l'ai fait maintenant. Mais le e.data est vide.


3 Réponses :


0
votes

J'ai trouvé l'inscription aux événements plus fiable. Et comme Adriano l'a dit, vous devriez probablement également rediriger le flux d'erreur. Voici un extrait de code qui devrait vous aider:

process.EnableRaisingEvents = true; 
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += process_Output;
process.ErrorDataReceived += process_Error;

void process_Output(object sender, DataReceivedEventArgs e)
{
    //e.Data would contain a line
    var outputLine = e.Data;
}

void process_Error(object sender, DataReceivedEventArgs e)
{
    var errorLine = e.Data;
}


4 commentaires

J'ai ajouté votre suggestion dans le code et mis un point d'arrêt dans les deux méthodes mais le programme n'y entre jamais.


ici devrait également être un appel process.BeginOutputReadLine ()


Avez-vous également redirigé RedirectStandardError, je l'ai mis à jour ci-dessus. Vous devez également ajouter ces lignes avant d'appeler myProcess.Start ().


@Ali: J'ai ajouté votre recommandation mais elle n'est toujours pas entrée dans ces deux méthodes.



1
votes

Je pense que la meilleure pratique consiste à écrire la sortie exécutable dans un fichier texte externe, puis à lire à partir de ce fichier en utilisant la manière normale de lire les fichiers texte.


1 commentaires

Comment la sortie est-elle écrite dans un fichier externe?



0
votes

Pour comprendre ce qui ne va pas, vous pouvez également essayer de lire ErrorStream. Par exemple, MongoDB restore util écrit toutes les informations de la console dans ErrorStream au lieu de OutputStream. Je vous recommande d’essayer d’utiliser des écouteurs d’événements:

           var startInfo = new System.Diagnostics.ProcessStartInfo
            {
                FileName = exePath,
                Arguments = " ", //this could be tricky
                UseShellExecute = false,
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                CreateNoWindow = true
            };

            try
            {
                using (var process = new System.Diagnostics.Process())
                {
                    process.StartInfo = startInfo;

                    process.OutputDataReceived += (sender, args) => Logger.Warn("OutputStream: " + args.Data);
                    process.ErrorDataReceived += (sender, args) => Logger.Warn("ErrorStream: " + args.Data);

                    if (!process.Start())
                    {
                        // not started
                    }

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

                    if (!process.WaitForExit(60_000))
                    {
                        \\Process ended with timeout. 60_000";
                    }
                }
            }
            catch (Exception e)
            {
                \\ O_o
                throw;
            }


0 commentaires