2010-02-27 17 views
6

Sé que hay stdout/in/err para un programa y quiero redirigir la salida de un programa a un archivo en lugar de la salida de la consola. Y ahora lo averigüe con el código de abajo:¿Cómo escribir en StdOut Stream de un programa directamente en C#?

FileStream fs = File.Open(@"E:\console.txt", FileMode.OpenOrCreate); 
StreamWriter sw = new StreamWriter(fs); 
TextWriter old = Console.Out; 
Console.SetOut(sw); 
Console.Write("bbb"); 
sw.Flush(); 

Pero este enfoque es conectar el programa de salida estándar a Console.Out y redirigir la Console.Out al archivo. Es una especie de la siguiente manera:

Program.StdOut -> Console.Out -> Archivo

El Console.Out aquí parece ser un puente. No quiero este puente y no quiero usar Console.Write() para hacer la salida. ¿Cómo podría asignar la secuencia estándar del programa al archivo de destino directamente y escribir en la salida estándar del programa directamente en lugar de Console.Write()? Lo que quiero es algo así como esto:

Program.StdOut -> Archivo

El Process.StandardOutput propiedad sólo me da un objeto de sólo lecturaStreamReader. Cómo escribir en Process.StandardOutput? ¿O dónde está el stdout del programa ?

Muchas gracias.

Respuesta

6

Puede obtener una bodega de la salida estándar de la aplicación llamando Console.OpenStandardOutput. Desde allí, puedes hacer lo que quieras con la transmisión, aunque no podrás reasignarla. Si desea hacerlo, deberá llamar a P/Invoke SetStdHandle y manejar los detalles usted mismo.

EDIT: Añadido código de ejemplo para el P/Invoke ruta:

[DllImport("kernel32.dll", SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool SetStdHandle(int nStdHandle, IntPtr nHandle); 

const int STD_OUTPUT_HANDLE = -11; 

static void RedirectStandardOutput(FileStream file) 
{ 
    SetStdHandle(STD_OUTPUT_HANDLE, file.SafeFileHandle.DangerousGetHandle()); 
} 
+0

Gracias, MikeP. Me pregunto por qué dejar que la clase Console reclame el método OpenStandardOutput(), por qué no categorizar este método en la clase Process, creo que sería más razonable. ¿Qué tipo de filosofía de diseño está involucrado? – smwikipedia

+0

No sé por qué eligieron este método. – MikeP

1

use las clases ProcessStartInfo y Process y configure RedirectStandardOutput en true, luego puede capturar el resultado de una secuencia.

ProcessStartInfo info = new ProcessStartInfo("process.exe", "-arg1 -arg2"); 
info.RedirectStandardOutput = true; 
Process p = Process.Start(info); 
p.Start(); 
string output = p.StandardOutput.ReadToEnd(); 
+1

Gracias, Jake. Quiero saber que en process.exe, ¿cómo escribir en la salida estándar del programa? ¿Qué tipo de código implementa eso? ¿Sigue siendo una Console.Write()? ¿Hay alguna manera de no usar este método y escribir directamente en la salida estándar del programa? – smwikipedia

+0

Necesita imprimir la salida del programa tanto para StdOut como para su segunda transmisión.Una forma es escribir un bucle llamando a 'ReadToEnd()', escribir en ambas salidas, luego dormir un poco, repetir hasta que la transmisión se haya cerrado. – spoulson

+0

Establezca 'info.UseShellExecute = false' y' p.StanardInput.Write() 'para enviar datos al proceso. Si el proceso hace eco de los datos, está bien, pero no puede secuestrar el proceso y usar su identificador StandardOutput como propio. – Jake

6

Probablemente no debe establecer la salida estándar de su propio proceso. La razón por la cual está estandarizada es para que la persona que llama (línea de comando, lo que sea) pueda redirigirla a donde sea necesario, sin que su programa tenga que saberlo.

Así funcionan cosas como "escriba foo.txt | more". Si el comando type se sintiera libre para redefinir stdout a un archivo, eso no funcionaría en absoluto.

Si desea escribir en una secuencia, simplemente abra la secuencia y escriba en ella.

Cuestiones relacionadas