Je développe une application Windows Forms qui m'oblige à appeler un programme distinct pour effectuer une tâche. Le programme est une application console et j'ai besoin de rediriger la sortie standard de la console vers une TextBox dans mon programme.
Je n'ai aucun problème à exécuter le programme à partir de mon application, mais je ne sais pas comment rediriger la sortie vers mon application. J'ai besoin de capturer la sortie pendant que le programme s'exécute à l'aide d'événements.
Le programme de la console n'est pas censé s'arrêter jusqu'à ce que mon application s'arrête et que le texte change constamment à intervalles aléatoires. Ce que j'essaie de faire, c'est simplement accrocher la sortie de la console pour déclencher un gestionnaire d'événements qui peut ensuite être utilisé pour mettre à jour la TextBox.
J'utilise C # pour coder le programme et j'utilise le framework .NET pour le développement. L'application d'origine n'est pas un programme .NET.
EDIT: Voici un exemple de code de ce que j'essaie de faire. Dans ma dernière application, je remplacerai Console.WriteLine par du code pour mettre à jour la TextBox. J'ai essayé de définir un point d'arrêt dans mon gestionnaire d'événements, et il n'est même pas atteint.
void Method()
{
var p = new Process();
var path = @"C:\ConsoleApp.exe";
p.StartInfo.FileName = path;
p.StartInfo.UseShellExecute = false;
p.OutputDataReceived += p_OutputDataReceived;
p.Start();
}
static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(">>> {0}", e.Data);
}
Cela fonctionne pour moi:
void RunWithRedirect(string cmdPath)
{
var proc = new Process();
proc.StartInfo.FileName = cmdPath;
// set up output redirection
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.EnableRaisingEvents = true;
proc.StartInfo.CreateNoWindow = true;
// see below for output handler
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
// output will be in string e.Data
}
Vous pouvez utiliser le code suivant
MemoryStream mem = new MemoryStream(1000);
StreamWriter writer = new StreamWriter(mem);
Console.SetOut(writer);
Assembly assembly = Assembly.LoadFrom(@"C:\ConsoleApp.exe");
Assembly.EntryPoint.Invoke(null, null);
writer.Close();
string s = Encoding.Default.GetString(mem.ToArray());
mem.Close();
J'ai ajouté un certain nombre de méthodes d'assistance à la O2 Platform (projet Open Source) qui vous permettent de scripter facilement une interaction avec un autre processus via la sortie et l'entrée de la console (voir http://code.google.com/p/o2platform/source/browse/trunk/O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs )
L'API permet également d'afficher la sortie de la console du processus en cours (dans un contrôle existant ou une fenêtre contextuelle). Voir cet article de blog pour plus de détails: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (ce blog contient également des détails sur la façon de consommer la sortie console de nouveaux processus)
Merci à Marc Maxham pour sa réponse qui me fait gagner du temps!
Comme le remarque Jon of All Trades, UseShellExecute
doit être défini sur false afin de rediriger les flux IO, sinon l'appel Start()
lance un InvalidOperationException
.
Voici ma modification du code où txtOut
est une zone de texte WPF en lecture seule
void RunWithRedirect(string cmdargs)
{
var proc = new Process()
{
StartInfo = new ProcessStartInfo("cmd.exe", "/k " + cmdargs)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
},
EnableRaisingEvents = true
};
// see below for output handler
proc.ErrorDataReceived += proc_DataReceived;
proc.OutputDataReceived += proc_DataReceived;
proc.Start();
proc.BeginErrorReadLine();
proc.BeginOutputReadLine();
proc.WaitForExit();
}
void proc_DataReceived(object sender, DataReceivedEventArgs e)
{
if (e.Data != null)
Dispatcher.BeginInvoke(new Action( () => txtOut.Text += (Environment.NewLine + e.Data) ));
}