c++ - que - ¿Dónde se escribe "printf" en una aplicación de Windows sin consola?
getstdhandle c++ (4)
Si elijo crear una aplicación de Windows sin consola e implementar printf/cout
en el código, ¿dónde escribe printf/cout
? ¿Escribe en el buffer stdout
? En caso afirmativo, ¿hay alguna forma de leerlo desde stdout
e imprimirlo en algún archivo de texto o hacer un MessageBox
con el texto (solo para verificar que lo he leído correctamente)?
EDITAR :: Solo para aclarar que no quiero redirigir la salida a ninguna parte. Me gustaría saber, ¿dónde escribe printf/cout
? Y si se escribe en algún búfer predeterminado, ¿hay una manera de leer la salida, solo para verificar que he leído la salida correcta y del búfer correcto? Por favor, no me den soluciones para redirigir el "stdout" .
Bajo Windows stdout
es un contenedor para las funciones de bajo nivel que acceden al identificador devuelto por GetStdHandle(STD_OUTPUT_HANDLE)
.
Al iniciar una aplicación que no sea de consola haciendo doble clic (probé con Windows 7, 64 bit), GetStdHandle(STD_OUTPUT_HANDLE)
devolverá un identificador no válido. Esto significa que printf
y otros comandos no escribirán nada en absoluto, pero las funciones de bajo nivel llamadas internamente por printf
devolverán un código de error.
Sin embargo, como ya se dijo, incluso un programa que no sea de consola se puede iniciar de la siguiente manera:
program_name > output_file.txt
En este caso, la salida de printf
se escribirá en el archivo de salida.
- EDITAR -
Si desea "capturar" la salida de printf()
y escribirla en MessageBox()
hay dos maneras de lograr esto:
El primero ejecuta el programa dos veces, mientras que la entrada de una instancia es la salida estándar de la otra. El comportamiento podría explicarse por la siguiente línea de comando:
program_name | program_name /msgbox
La segunda posibilidad funciona sin ejecutar dos programas y sin ejecutar el programa dos veces: puede enganchar el identificador de archivo # 1. Esto debería ser al menos posible cuando se usa msvcrt.dll:
HANDLE hRead,hWrite;
CreatePipe(&hRead,&hWrite,NULL,0);
dup2(_open_osfhandle(hWrite,O_WRONLY),1);
// Now printf() output can be read from handle hRead
printf("Hello world 2!/n");
// In a separate thread do:
ReadFile(hRead,...);
Debido a que su pregunta parece ser solo informativa, una aplicación de Windows sin consola tiene su stdout, stderr se cierra. Cualquier función que intente dar salida a esos manejadores, simplemente recibe una llamada, busca un manejador abierto, lo encuentra cerrado y regresa sin hacer nada más.
Se podría decir que, en este caso, su resultado no se encuentra en ninguna parte :)
Si desea leer esta salida, necesita abrir los manejadores ya sea asignando una consola o usando uno de los métodos descritos aquí.
Estoy desarrollando un motor visual y utilizo las siguientes dos cosas como una sustitución de la entrada / salida estándar entre la PC y el usuario que obtiene en la aplicación de consola.
1: Utilice sprintf
(int sprintf ( char * str, const char * format, ... ))
. Lo que hace es imprimir en una cadena en lugar de stdout (no tiene que usar un archivo temporal). Después de esto, puede usar MessageBox
con la cadena donde acaba de imprimir.
2: Cree una ventana de consola real (mientras mantiene la ventana principal) y redirija el stdin
, stdout
y stderr
de la ventana principal a la consola. Aquí hay una clase para la construcción:
ConsoleWindowClass.h:
#pragma once
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <fstream>
class ConsoleWindowClass
{
public:
ConsoleWindowClass(void);
~ConsoleWindowClass(void);
void Create();
};
ConsoleWindowClass.cpp:
#include "ConsoleWindowClass.h"
using namespace std;
// maximum mumber of lines the output console should have
static const WORD MAX_CONSOLE_LINES = 500;
ConsoleWindowClass::ConsoleWindowClass(void)
{
Create();
}
ConsoleWindowClass::~ConsoleWindowClass(void)
{
}
void ConsoleWindowClass::Create()
{
int hConHandle;
long lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),&coninfo);
coninfo.dwSize.Y = MAX_CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE),coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stdout = *fp;
setvbuf( stdout, NULL, _IONBF, 0 );
// redirect unbuffered STDIN to the console
lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "r" );
*stdin = *fp;
setvbuf( stdin, NULL, _IONBF, 0 );
// redirect unbuffered STDERR to the console
lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen( hConHandle, "w" );
*stderr = *fp;
setvbuf( stderr, NULL, _IONBF, 0 );
// make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog
// point to console as well
ios::sync_with_stdio();
}
Después de esto, llamar a printf()
imprimirá la cadena en la consola. También puede usar la consola para escribir cadenas en ella y se podrán utilizar desde la ventana principal (use subprocesos múltiples para que scanf
no detenga su programa principal).
printf
o cout
siempre imprime a stdout
.
Debe iniciar el programa desde la línea de comandos y canalizar su salida a un archivo de texto para que sea legible.
De lo contrario, necesitaría una secuencia de salida a un archivo en tmp para generarse dentro de su código.
La canalización se puede hacer de la siguiente manera (si el nombre de su aplicación es foo):
foo > log.txt
Luego puede leer el archivo log.txt
si navega a su directorio que se puede encontrar con
dir