Executer une commande et recuperer la sortie standard - C#/.NET managed - Programmation
Marsh Posté le 23-05-2007 à 11:40:10
je dirais déjà de lire après le "waitforexit"
Marsh Posté le 31-05-2007 à 14:12:45
bon en fait j'ai trouver le probleme mais pas la solution. Ce que je veut faire c pouvoir lancer un programme en console et afficher le resultat dans un label sur une page aspx. Le probleme c que ca marche que si le programme a un temp d'execution relativement court genre un "ping google.fr" fonctionne tres bien mais pas le programme que je veux lancer qui lui met plus de temps. J'ai cherché une facons d'augmenter le timeout pour que le programme ai le temp de s'executer, mais je n'ai rien trouver.
donc voila le code qui fonctionne pour un ping.
public bool Execute(string executable, string arguments)
{
Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = executable;
proc.StartInfo.Arguments = arguments;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
lblConsole.Text += executable + " " + arguments;
while (!proc.HasExited)
lblConsole.Text += "<br>" + proc.StandardOutput.ReadLine();
if(proc.ExitCode != 0)
return false;
return true;
}
Je sais pas si ca joue mais le label est dans une page ascx que j'appelle dans une autre page aspx, mais ca ne devrais pas venir de ca.
Si vous avez une idée n'hesiter pas.
Marsh Posté le 31-05-2007 à 14:15:42
est ce qu'il existe un commande bash windows qui permet de lancer une appli en background comme sous linux pour que le processus continue de s'executer?
Je sais que dans ce cas je ne pourrais pas voir l'affichage mais bon si c le seul moyens de le faire.
Marsh Posté le 12-06-2007 à 14:22:39
Plop !
J'ai aujourd'hui une question similaire.
Je veux pouvoir lancer un traîtement (ici un *.bat pour mes tests) qui peut prendre du temps. Je veux pouvoir récupérer à l'écran la sortie au fur et à mesure de son exécution. Notamment dans l'objectif de pouvoir interagir graphiquement avec le traîtement : un bouton annulé pour quitter le traîtement en cours, copier pour prendre la sortie dans le presse papier, etc.
Le problème, c'est que mon évènement "p_OutputDataReceived" ne tourne pas dans le même thread que mon TextBox1 et du coup je ne peux pas communiquer.
Avec un thread fabriqué "à la main", je sais comment jouer avec des delegate (enfin... je sais... y'a des exemples tous fais dans la MSDN ) pour le faire, mais dans le cas d'un process je ne sais pas du tout...
Code :
|
Marsh Posté le 12-06-2007 à 15:46:08
En utilisant un background worker avec un override du eventargs pour le déclenchement d'un progress. tu lève un evnmt progress à chaque récupération de sortie afin de revenir dans le thread principal. Grâce au eventargs, tu peux récupérer les nouvelles valeurs à afficher dans ton textbox.
exemple ici : http://windowsclient.net/downloads [...] y1305.aspx
Marsh Posté le 12-06-2007 à 15:47:11
euh... merci
rien pigé à ton explication, je vais regarder le lien
Marsh Posté le 12-06-2007 à 15:56:47
MagicBuzz a écrit : euh... merci |
C'est simple, plutot que d'utiliser un Thread, (System.threading), utilise un Background worker. Ce dernier à la particularité de pouvoir retourner des évennements au thread appelant (typiquement le thread principal de ta fenêtre), à savoir , un evenement Progress et un évennement End, respectivement, un évennement que tu peux déclencher à tout moment dans ton "Thread" de backgroundWorker et un évennement de fin d'execution de la tâche "Threadée" de ton backgroundWorker.
Celui qui nous interesse le plus est l'evennement progress qui peux appeler un délégué dans le thread principal, celui ci remonte un evennement classique (object sender, progressEventArgs e). De base, le progressEventArgs ne propose qu'un entier de "progression" (une valeur entiere, un pourcentage de progression typiquement, que tu affecte dans ton traitement threadé à chaque 'Itération'). En surchargeant cet evenement pour pouvoir par exemple retourner un tableau de string, Cela te permet dans ton thread, d'instancier ton progressEventArgs en affectant les nouvelles chaines de caracteres dans le tableau et de le retourner au thread principal en déclenchant l'évennement.
Pour info, le background worker du framework 2.0 ne fait que simplifier des appels à des invoke/beginInvoke. Voici une simplification de son fonctionnement
http://www.codeproject.com/csharp/workerthread.asp
Marsh Posté le 12-06-2007 à 17:39:45
Merci beaucoup !
J'ai pondu ça... (pas eu trop le temps de me pencher dessus)
Ca marche, mais j'en suis pas trop content à cause des 3 lignes en commentaire... Le souci c'est que si je les mets pas en commentaire, mon thread fils attends que le thread père ait fini d'attendre le thread fils et... du coup ça freeze
FVaudra que je me penche un peu mieux dessus ce soir. En tout cas, c'est cool j'arrive à voir mon ping se dérouler tranquillement donc c'est un bon début.
Merci !
Code :
|
Marsh Posté le 12-06-2007 à 17:42:32
C'est pour cela que j'aurais plutot penché pour Lancer ton Batch DANS le thread d'un background worker
Marsh Posté le 14-06-2007 à 11:22:46
Plop, c'est moi que revoilà
Je viens de mettre en place la solution avec un backgroundworker (en fait, j'ai pigé tout à l'heure que c'est une class du framework )
Ca "marche", c'est à dire que mon script marche bien, et j'arrive bien à inter-agir avec ma form durant le traîtement.
Par contre là où ça déconne, c'est que je ne récupère rien dans mon StandardOutput !
En effet, sortie :
|
Code :
Code :
|
Le script :
|
Vu que j'ai bien "coin coin" qui apparaît, c'est qu'à priori, mon script se lance bien, et que je vais correctement lire mon standardoutput qui n'est pas vide...
De plus, le "yo" n'apparaît pas avant quelques secondes, ce qui correspond au temps nécessaire pour le ping... Bref, ça m'a l'air de marcher !
Sauf que... Bah j'ai rien comme résultat.
C'est quoi qui va pas encore ?
Marsh Posté le 14-06-2007 à 12:41:06
Je viens de désactiver la récupération du standardoutput et faire tourner le script dans une fenêtre.
Comme je le pensais, il s'exécute pourtant bien et est verbeux comme prévu
Mais pourtant je récupère rien dans mon programme
Marsh Posté le 14-06-2007 à 15:00:54
MagicBuzz a écrit : Je viens de désactiver la récupération du standardoutput et faire tourner le script dans une fenêtre. |
Désolé, là, je ne pourrais pas trop t'aider, j'avais deja fais ça il y a super longtemps mais j'ai plus trop le truc en tête.
Une petite recherche sur codeproject peut-être ?
Marsh Posté le 14-06-2007 à 15:10:26
ixemul a écrit : Désolé, là, je ne pourrais pas trop t'aider, j'avais deja fais ça il y a super longtemps mais j'ai plus trop le truc en tête. |
le vrai problème, c'est que pourtant j'ai le même code que dans l'exemple qui marche !
c'est là en fait que je comprends pas pourquoi eux ça marche et moi ça marche pas
bon, vais creuser un peu
Marsh Posté le 14-06-2007 à 15:11:45
MagicBuzz a écrit : le vrai problème, c'est que pourtant j'ai le même code que dans l'exemple qui marche ! |
Sans BackgroundWorker, ça marche ? (un simple Console.Writeline)
Marsh Posté le 14-06-2007 à 15:36:22
Bon, ben dans l'exemple ils passaient par un objet hérité de INotifyPropertyChanged pour raiser l'event Progress du BackgroundWorker, mais c'est pas ça...
Code :
|
J'utilise ça à la place de ma simple String mais ça marche pas mieux
Marsh Posté le 14-06-2007 à 15:37:22
ixemul a écrit : Sans BackgroundWorker, ça marche ? (un simple Console.Writeline) |
Je vais voir... J'en doute (si je colle des points d'arrêts, mais variables sont toujours vides)
Marsh Posté le 14-06-2007 à 15:40:30
J'ai essayé avec un MessageBox.Show(line) et ça ne marche pas mieux (elle apparaît une fois, et vide)
Ligne 57 dans mon code
Marsh Posté le 14-06-2007 à 15:59:32
Dans mon code, si aux lignes 29 à 32 j'inverse les valeurs booléennes.
Et que je commente les lignes 40 à 77, j'obtiens ça :
=> Donc le script tourne bien.
Par contre, si je remets normalement et colle un point d'arrêt sur la ligne 56, le code n'y passe qu'une seule fois, et line = "", ce qui ne me semble pas normal du tout.
PAR CONTRE si en fin de script je colle un "copy c:\in\test.bat c:\in\test.old" j'ai bien un fichier qui se crée, donc le script s'exécute tout de même entièrement. Mais pour une raison totalement inconnue, je n'ai rien dans la sortie standard
Avec l'exemple (de ton premier lien) le point d'arrêt est visité plusieurs fois et line n'est jamais vide...
Si je fais "ReadToEnd()" au lieu de "ReadLine()" à la ligne 56, j'obtiens ça... à la fin de l'exécution (donc exécution synchrone, donc pas ce que je veux )
|
Marsh Posté le 14-06-2007 à 17:18:48
Bon, ben si quelqu'un n'a rien à foutre de la soirée, voici mon programme complet... Quand on fait un click droit sur l'icône et qu'on choisi une entrée dans le context menu, ça doit lancer le script "toto.bat" qui se trouve dans c:\in (à créer par vos soins).
Et dans la fenêtre qui s'ouvre, je suis censé avoir le mode verbeux du script, mais ça marche pas
http://membres.lycos.fr/magicbuzz/files/
Le fichier "NetAdmin.zip"
Marsh Posté le 18-06-2007 à 11:06:52
Bon, c'est encore moi...
C'est vraiment incompréhensible...
Si je met un point d'arrêt sur "while(!done)" ça marche sans problème : ça affiche bien la progression du script, et en temps réel comme désiré (à chaque fois que je fais "F5" ça m'affiche effectivement ce qu'il s'est passé entre temps)
Mais si je ne fais pas de point d'arrêt, ça fait que dalle
Marsh Posté le 18-06-2007 à 11:21:24
Total n'importe quoi...
Si j'ajoute des Debug.WriteLine(), selon où je les met, ça marche ou ça marche pas... Ou même ça marche à moitié (ça affiche le résultat de la première instruction de mon script - un dir *.* - mais pas la seconde - un ping - que je peux quand même récupérer à l'aide un "ScriptProcess.StandardOutput.ReadToEnd()" juste avant de détruire mon objet
Putain mais ça me gave c'est quoi ce bordel encore ? Un bug du framework ou quoi ???
Marsh Posté le 18-06-2007 à 11:59:24
Bon, j'ai trouvé une parade.
Visiblement "Peek()" c'est de la merde en branche daubé jusqu'à la dernière ligne, donc :
Code :
|
Les bonnes grosses méthodes de VBistes sont toujours les meilleurs : les plus crades, mais qui marchent
Marsh Posté le 18-06-2007 à 12:16:40
http://jab.developpez.com/tutoriel [...] synchrone/
Ca m'a l'air plus simple sa méthode à lui...
VIII. Récupérer des informations affichées par le processus externe
-B. En utilisant un thread
Marsh Posté le 23-05-2007 à 10:41:26
Salut a tous,
Bon je vous explique j'aimerais executer une commande et recuperer la sortie standard pour pouvoir l'afficher dans un label. J'ai créée la fonction suivantes mais ca ne marche toujours pas. Vous avez une idée pourquoi ca marche pas?
public bool Execute(string executable, string arguments)
{
Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = executable;
proc.StartInfo.Arguments = arguments;
proc.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false; // <- C'etais demander pour pouvoir recuperer la sortie standard.
proc.Start();
lblConsole.Text += proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
if (proc.ExitCode != 0)
return false;
return true;
}
---------------
____