winapi stdout redirect stderr

winapi - ¿Puedo capturar stdout/stderr por separado y mantener el orden original?



redirect (6)

En realidad, no lo pensaría, pero std_out está bajo el control de los diseñadores del sistema; exactamente cómo y cuándo se escribe std_out está sujeto al planificador del sistema, que según mis pruebas está subordinado a problemas que no están documentados.

Estaba escribiendo algunas cosas un día e hice algo de trabajo en uno de los dispositivos del sistema mientras tenía el código abierto en el editor y descubrí que el sistema daba prioridad en tiempo real al controlador, dejando mi c- cuidadosamente diseñado. código en algún lugar aproximadamente una décima parte tan importante como el código propietario.

Revertir eso para que pueda obtener un orden secuencial de las escrituras será un reto, por decir lo menos.

Escribí una aplicación de Windows usando la API win32 nativa. Mi aplicación lanzará otros procesos y capturará la salida y resaltará la salida de stderr en rojo.

Para lograr esto, creo un canal separado para stdout y stderr y los utilizo en la estructura STARTUPINFO cuando llamo CreateProcess. Luego, lanzo una cadena separada para cada identificador stdout / stderr que se lee desde la tubería y registra la salida en una ventana.

Esto funciona bien en la mayoría de los casos. El problema que tengo es que si el proceso secundario se conecta a stderr y stdout en una sucesión rápida, mi aplicación a veces mostrará el resultado en el orden incorrecto. Supongo que esto se debe al uso de dos hilos para leer en cada mango.

¿Es posible capturar stdout y stderr en el orden original en el que fueron escritos, a la vez que se puede distinguir entre los dos?


Estoy bastante seguro de que no se puede hacer, salvo escribir el programa generado para escribir en paquetes y agregar un sello de tiempo para cada uno. Sin eso, normalmente se puede planificar el almacenamiento en búfer en la biblioteca estándar del proceso secundario, por lo que, cuando se transmitan a través del conducto al padre, es muy probable que ya no estén funcionando.


Puede redirigir stderr a stdout:

command_name 2>&1

Esto es posible en C usando tuberías, según recuerdo.

ACTUALIZACIÓN: Oh, lo siento, me perdí la parte sobre poder distinguir entre los dos. Sé que TextMate lo hizo de alguna manera usando un código visible para el usuario ... No lo he buscado por un tiempo, pero lo echaré un vistazo. Pero después de pensar un poco más, ¿podrías usar algo como Open3 en Ruby? Tendría que mirar tanto STDOUT como STDERR al mismo tiempo, pero realmente nadie debería esperar un cierto orden de salida con respecto a estos dos.

ACTUALIZACIÓN 2: Ejemplo de lo que quise decir en Ruby:

require ''open3'' Open3.popen3(''ruby print3.rb'') do |stdin, stdout, stderr| loop do puts stdout.gets puts stderr.gets end end

... donde print3.rb es simplemente:

loop do $stdout.puts ''hello from stdout'' $stderr.puts ''hello from stderr'' end

En lugar de arrojar la salida directamente a las puts , podría enviar un mensaje a un observador que lo imprimiría en su programa. Lo siento, no tengo Windows en esta máquina (o cualquier disponible de inmediato), pero espero que esto ilustre el concepto.


Estoy bastante seguro de que incluso si no los separa en absoluto, aún no está garantizado que se intercambien entre sí en el orden correcto.


Como la intención es anotar el resultado de un programa existente, cualquier posible entrelazado de las dos secuencias debe ser correcto. El desarrollador original habrá realizado las llamadas flush () apropiadas para garantizar el cumplimiento de los pedidos obligatorios.

Como se explicó anteriormente, registre cada fragmento escrito con una marca de tiempo y utilícelo para recuperar la secuencia que realmente ven los dispositivos de salida.


En la mayoría de las implementaciones de stdout y stderr que he visto, stdout está almacenado en memoria intermedia y stderr no. Básicamente, lo que esto significa es que no se garantiza que estén en orden incluso cuando se ejecuta el programa en línea de comando.

http://en.wikipedia.org/wiki/Stderr#Standard_error_.28stderr.29

La respuesta breve: no puede asegurarse de leer las líneas en el mismo orden en que aparecen en cmd.exe porque no se garantiza el orden en que aparecen en cmd.exe.