Lancement d'un process DOS + Récupération de l'output

Résolu
Fly95 Messages postés 6 Date d'inscription lundi 25 octobre 2004 Statut Membre Dernière intervention 21 mai 2007 - 18 mai 2007 à 15:44
zygou Messages postés 2 Date d'inscription mardi 13 janvier 2009 Statut Membre Dernière intervention 25 mai 2009 - 25 mai 2009 à 18:34
Salut,

je suis en train de programmer un outil permettant de lancer des processus de copie. Ces processus se servent en partie de XCOPY et d'autres API, toutes lancées via des commandes Dos.

Cependant, pour un confort d'utilisation, j'essaye de rendre transparent, pour les utilisateurs, l'utilisation de ces commandes Dos. Pour cela, je lance un processus via le code C#, et je récupère la StandardOutput, que je redirige vers une RichTextBox. Malheureusement, lorsque j'active la redirection du StandardOutput, le processus ne s'exécute plus du tout... Et je ne récupère pas non plus la sortie dans la RichTextBox.

Avant de poster, j'ai cherché sur les forums, et après moultes recherches et tentatives via des sources fournis, je me suis résigné à venir vous déranger...

Quelqu'un saurait-il pourquoi la redirection des messages de sortie ne fonctionne pas ? Et si oui, comment faire pour récupérer tout ça ?

Merci d'avance de votre aide !

Voici le code utilisé à l'heure actuelle :
//Lancement du process
process.StartInfo =
new
ProcessStartInfo(monappli,
arguments);
process.StartInfo.UseShellExecute =
false;
process.StartInfo.CreateNoWindow =
true;
process.StartInfo.RedirectStandardError =
true;
process.StartInfo.RedirectStandardOutput =
true;
process.OutputDataReceived +=
new
DataReceivedEventHandler(process_OutputDataReceived);
process.ErrorDataReceived +=
new
DataReceivedEventHandler(process_ErrorDataReceived);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
A voir également:

10 réponses

cs__Syl_ Messages postés 66 Date d'inscription vendredi 20 octobre 2006 Statut Membre Dernière intervention 25 février 2008 2
18 mai 2007 à 16:31
??? Je recommence

Je ne sais pas comment utiliser les objets gérant l'outpout cela dit en DOS on peut rediriger le résultat d'une commande vers un fichier.

Une solution peu propre, car utilisant une écriture sur le disque, serait de rajouter "> logX.txt" (qui signifie écrire le résultat de la commande dans le fichier logX.txt, X étant le "numéro" de ta commande) à la fin de chacune de tes commandes dos
exemple : "ipconfig > ipconfig.txt" va créer (où écraser) le fichier ipconfig.txt et le remplir du résultat de la commande ipconfig
Ensuite tu peux lire le contenu de chacun des logs et l'ajouter à ta RichTextBox
Puis supprimer les log.

Il y a sûrement une meilleure solution.

Bonne journée

_Syl_
0
Fly95 Messages postés 6 Date d'inscription lundi 25 octobre 2004 Statut Membre Dernière intervention 21 mai 2007
18 mai 2007 à 16:44
Salut !

En effet, j'avais pensé passer cette méthode, mais c'est pas très propre malheureusement. L'outil que je développe est pour une entreprise, je dois donc réussir à garder les temps d'exécution et la prise d'espace le plus bas possible.

J'envisagerai cette solution si et seulement si je n'arrive pas à trouver comment récupérer ce flux de sortie.

Merci pour ta réponse tout de même !

Fly.
0
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
18 mai 2007 à 18:32
Salut,

Pourtant le code en l'état devrait fonctionner...
Que fait tu dans les gestionnaires d'évènement ?
L'application lancée n'attendrais pas une saise de la part de l'utilisateur ?

/*
coq
MVP Visual C#
CoqBlog
*/
0
Fly95 Messages postés 6 Date d'inscription lundi 25 octobre 2004 Statut Membre Dernière intervention 21 mai 2007
18 mai 2007 à 20:20
Salut,

Ces lignes de code sont lancés lors d'un évènement click sur un bouton classique.
En gros, l'utilisateur régle ses variables via l'application csharp développée, puis, en me basant sur ces chaînes de caractères, je lance une commande XCOPY qui récupère des données à partir d'un serveur vers le poste client.

Aucun input n'est nécessaire de la part de l'utilisateur lorsque le processus se lance, puisque je passe directement la commande complète. De plus, lorsque j'effectue exactement les mêmes appels, sans rediriger la sortie, la fenêtre Dos s'ouvre et inscrit bien tous les fichiers copiés, les uns à la suite des autres.

Merci pour vos commentaires.
Je continue à chercher encore et toujours, mais je ne vois pas trop... Surtout que j'ai un code sur une autre application, qui fait exactement les mêmes appels, et qui fonctionne parfaitement !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Fly95 Messages postés 6 Date d'inscription lundi 25 octobre 2004 Statut Membre Dernière intervention 21 mai 2007
18 mai 2007 à 21:13
Ok, je vois ce dont tu parles.

J'ai utilisé des threads aujourd'hui et je vois la problématique ! Ca va pas être simple parce que j'ai encore un peu de mal avec les Threads, mais je vais y arriver.

L'important étant que le texte s'affiche "en temps réel" et pas d'un bloc, car l'utilisateur doit avoir du feedback pour connaître l'avancement de la copie.

Merci pour votre aide.
0
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
18 mai 2007 à 21:15
De rien :-)

/*
coq
MVP Visual C#
CoqBlog
*/
0
Fly95 Messages postés 6 Date d'inscription lundi 25 octobre 2004 Statut Membre Dernière intervention 21 mai 2007
21 mai 2007 à 18:22
Et... Je reviens à la charge !

Bon, c'est pas fameux fameux tout mon code, mais je commence à arriver à afficher quelquechose. Ce n'est malheureusement pas suffisant car il me semble que la moitié des informations "normalement" affichées par la commande Dos passent à la trappe...

Je pense que je dois utiliser un processus asynchrone pour récupérer les sorties de l'output et les afficher dans ma richTextBox. Cependant, je n'arrive pas à trouver d'exemples parlants pour me baser dessus.

Si quelqu'un avait l'amabilité de me fournir ça, je le suis en serais très reconnaissant.
Merci d'avance !
0
zygou Messages postés 2 Date d'inscription mardi 13 janvier 2009 Statut Membre Dernière intervention 25 mai 2009
25 mai 2009 à 17:23
Bonjour,
je m'excuse de remonter ce vieux sujet mais il me semble que c'est le sujet le plus proche que j'ai lu sur ce forum concernant mon probleme :
j'ai un problème concernant la lecture de la sortie standard d'un processus.

je me suis d'abord fortement inspiré de cette page http://jab.developpez.com/tutoriels/...ess/synchrone/ , ainsi que de la doc msdn pour la lecture syncrhone ou asynchrone mais je n'arrive pas à lire la sortie.


Donc pour revenir a mon programme, je lance un "process". durant
l'execution de ce processus la sortie standard evolue toute les
secondes. J'aimerai pouvoir enregistrer une de ces informations pour
faire évoluer une barre de chargement.


voila mes bout de code :

Code :
 
md = new MessageDialog (this, DialogFlags.DestroyWithParent,
MessageType.Info, ButtonsType.Cancel,"test","");

//on crée le thread de lecture des infos
Thread readInfo = new Thread(new ThreadStart(this.readOutput));

ProcessStartInfo processInfo = new ProcessStartInfo("povray");
processInfo.Arguments = InfoProj.getPathProj() + InfoProj.getNameProj() + ".ini";

//on déroute la sortie standard
processInfo.UseShellExecute = false;
processInfo.CreateNoWindow = true;
processInfo.RedirectStandardOutput = true;
outPov = new StringBuilder("");

povRender = new Process();
povRender.StartInfo = processInfo ;
// on utilise l'événement pour savoir quand le processus est terminé
povRender.EnableRaisingEvents = true ;
povRender.Exited += new EventHandler(this.renderEnded);
 
povRender.Start();

// on démarre le thread de lecture
readInfo.Start();
// on affiche la fenêtre de progression

md.Run();

// On vérifie si le processus est fini.
// Si ce n'est pas le cas, l'utilisateur a appuyé sur stop
// et il faut fermer le processus. Le thread est fermé après l'arrêt
// du processus
if( !povRender.HasExited)
{
povRender.Kill();
povRender.WaitForExit();
}
 
exitCode = povRender.ExitCode ;
System.Console.WriteLine(exitCode);

povRender.Close();
textviewMain.Buffer.Text = myString ;
 
protectedvoid renderEnded(object sender, EventArgs args){
 
md.Destroy();

}
 
privatevoid readOutput()
{
while(! povRender.HasExited)
{
StreamReader povOutPut = povRender.StandardOutput ;
myString += povOutPut.ReadLine();
}
}

 

voila, je ne vous met pas mon test de lecture asynchrone, la seul difference
est que, au lieu d'un thread de lecture j'ai un
DataReceivedEventHandler et j'utilise la fonction
beginOutputReadLine(). Je précise que je n'ai pas d'ereur a la
compilation ou l'execution mais je recupere indubitablement un string
vide, alors que la "sortie de l'application" de mon IDE me montre bien
les informations que je cherche a récupérer


par contre je n'ai pas tres bien saisie la difference entre lecture
synchrone de la sortie et lecture asynchrone. Dans mon cas laquelle me
conseilleriez vous ?


Je vous remercie d'avance pour vos reponses, en esperant avoir été le plus clair possible

Jerome
0
zygou Messages postés 2 Date d'inscription mardi 13 janvier 2009 Statut Membre Dernière intervention 25 mai 2009
25 mai 2009 à 18:34
Re, désolé pour le double post mais je n'ai pas trouvé la fonction éditer ...
et bien j'ai un peu honte mais je ne récupère rien dans la sortie standard car mon processus n'écrit rien dans la sortie standard :s les information que je souhaite récupérer dans ce processus semble en faite redirigé vers la sortie de mon application ...
je ne comprend pas vraiment encore pourquoi mais je vais chercher de ce coté et je devrai resoudre mon probleme rapidement
je vous prie de m'excuser pour le dérangement
jerome
0
cs_coq Messages postés 6349 Date d'inscription samedi 1 juin 2002 Statut Membre Dernière intervention 2 août 2014 101
18 mai 2007 à 20:49
Tu utilises Invoke dans tes gestionnaires d'évènement ?
Si c'est le cas ça ne peut pas marcher en l'état, car dans le thread executant process_OutputDataReceived tu lances une opération dans le thread du GUI qui lui même ne peut effectuer le traitement comme il attend que le processus se ferme.
Et comme le thread appelant attend que Invoke soit terminé...
Tu vas devoir utiliser BeginInvoke au lieu de Invoke : dans ce cas là le texte ne s'affichera pas ligne par ligne mais intégralement à la fin du traitement, mais au moins le traitement en lui même ne sera pas bloqué.
Si tu veux que ton affichage soit mit à jour ligne par ligne, il va falloir que tu mettes en place un lancement du process dans un autre thread, et un mécanisme de synchronisation non bloquant pour le GUI.

/*
coq
MVP Visual C#
CoqBlog
*/
-2
Rejoignez-nous