Domanda

Sto sviluppando un'applicazione Windows Form che mi richiede di chiamare un programma separato per eseguire un'attività. Il programma è un'applicazione console e devo reindirizzare l'output standard dalla console a una TextBox nel mio programma.

Non ho problemi a eseguire il programma dalla mia applicazione, ma non so come reindirizzare l'output alla mia applicazione. Ho bisogno di catturare l'output mentre il programma è in esecuzione utilizzando eventi.

Il programma della console non è destinato a interrompere l'esecuzione finché l'applicazione non si interrompe e il testo cambia costantemente a intervalli casuali. Quello che sto tentando di fare è semplicemente agganciare l'output dalla console per attivare un gestore eventi che può quindi essere utilizzato per aggiornare TextBox.

Sto usando C # per codificare il programma e sto usando .NET Framework per lo sviluppo. L'applicazione originale non è un programma .NET.

EDIT: Ecco un esempio di codice di ciò che sto cercando di fare. Nella mia app finale, sostituirò Console.WriteLine con il codice per aggiornare TextBox. Ho provato a impostare un punto di interruzione nel gestore dell'evento e non è nemmeno stato raggiunto.

    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);
    }
È stato utile?

Soluzione

Questo funziona per me:

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
}

Altri suggerimenti

Puoi usare il seguente codice

        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();

Ho aggiunto un certo numero di metodi di supporto alla Piattaforma O2 (progetto Open Source) che ti consentono di creare facilmente un script interazione con un altro processo tramite l'output e l'input della console (vedere http://code.google.com/p/o2platform/source/browse/trunk/O2_Scripts/APIs/Windows/CmdExe/CmdExeAPI.cs )

Utile anche per te potrebbe essere l'API che consente la visualizzazione dell'output della console del processo corrente (in una finestra di controllo o popup esistente). Vedi questo post del blog per maggiori dettagli: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (questo blog contiene anche dettagli su come consumare la console output di nuovi processi)

Grazie a Marc Maxham per la sua risposta che mi fa risparmiare tempo!

Come lo nota Jon of All Trades, UseShellExecute deve essere impostato su false per reindirizzare i flussi IO, altrimenti la chiamata Start () genera un InvalidOperationException .

Ecco la mia modifica del codice in cui txtOut è una casella di testo di sola lettura WPF

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) ));
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top