// some_wrp.exe
int main(int argc, char* argv[])
{
FILE* stream = freopen("file.txt", "w", stdout); // переопределяем вывод
_execv("some.exe", argv); // запускаем прогу
return 0;
}
Дублирование stdout в файл
Просто переопеределить вывод в файл проблем нет:
Код:
но нужно именно дублирование, т.е. аналог команды tee в линуксе.
На ум приходят только изощеренные методы через pipe. Может кто знает метод попроще?
Цитата:
Originally posted by Green
Подскажите элегантный способ дублирования вывода в stdout в файл? Т.е. есть некоторая (не моя) консольная программа, надо бы ее вывод на экран дублировать ещё и в файл.
Просто переопеределить вывод в файл проблем нет:
но нужно именно дублирование, т.е. аналог команды tee в линуксе.
На ум приходят только изощеренные методы через pipe. Может кто знает метод попроще?
Подскажите элегантный способ дублирования вывода в stdout в файл? Т.е. есть некоторая (не моя) консольная программа, надо бы ее вывод на экран дублировать ещё и в файл.
Просто переопеределить вывод в файл проблем нет:
Код:
// some_wrp.exe
int main(int argc, char* argv[])
{
FILE* stream = freopen("file.txt", "w", stdout); // переопределяем вывод
_execv("some.exe", argv); // запускаем прогу
return 0;
}
int main(int argc, char* argv[])
{
FILE* stream = freopen("file.txt", "w", stdout); // переопределяем вывод
_execv("some.exe", argv); // запускаем прогу
return 0;
}
но нужно именно дублирование, т.е. аналог команды tee в линуксе.
На ум приходят только изощеренные методы через pipe. Может кто знает метод попроще?
как я понял, у тебя есть исходники чужой программы? и прога под винду? если нет исходников, то через хук глобальный можно, но это тоже извращение.
Пришлось все же через pipe делать.
Вот код, если кому надо.
Код:
#include <io.h>
#include <stdio.h>
#include <process.h>
#include <fcntl.h>
#include <windows.h>
#define LOG_PROCESS "some.exe"
#define STDOUT_LOG "stdout.log"
#define WRITE_HANDLE 1
#define READ_HANDLE 0
int main(int argc, char* argv[])
{
int hStdOutPipe[2], hStdErrPipe[2];
int hStdOut = _dup(_fileno(stdout));
if( _pipe(hStdOutPipe, 512, _O_TEXT | O_NOINHERIT) == -1
|| _dup2(hStdOutPipe[WRITE_HANDLE], _fileno(stdout)) )
return 1;
_close(hStdOutPipe[WRITE_HANDLE]);
int hStdErr = _dup(_fileno(stderr));
if( _pipe(hStdErrPipe, 512, _O_TEXT | O_NOINHERIT) == -1
|| _dup2(hStdErrPipe[WRITE_HANDLE], _fileno(stderr)) )
return 1;
_close(hStdErrPipe[WRITE_HANDLE]);
FILE* pStdOutLog = fopen(STDOUT_LOG, "a");
if(!pStdOutLog) return 1;
fprintf(pStdOutLog, "# ");
for(int i=0; i<argc; i++)
fprintf(pStdOutLog, "%s ", argv);
fprintf(pStdOutLog, "\n");
HANDLE hProcess = (HANDLE)_spawnv(P_NOWAIT, LOG_PROCESS, (const char* const*)&argv[0]);
if(INVALID_HANDLE_VALUE == hProcess)
{
fprintf(pStdOutLog, "# Can't spawn process.\n");
fclose(pStdOutLog);
return 1;
}
if( !_dup2(hStdOut, _fileno(stdout)) ) _close(hStdOut);
if( !_dup2(hStdErr, _fileno(stderr)) ) _close(hStdErr);
DWORD nExitCode = STILL_ACTIVE;
if(hProcess)
{
int nOutRead;
char pBuffer[128];
while( STILL_ACTIVE == nExitCode || !_eof(hStdOutPipe[READ_HANDLE]) || !_eof(hStdErrPipe[READ_HANDLE]) )
{
if( !_eof(hStdOutPipe[READ_HANDLE]) )
{
nOutRead = _read(hStdOutPipe[READ_HANDLE], pBuffer, sizeof pBuffer);
if(nOutRead)
{
fwrite(pBuffer, 1, nOutRead, pStdOutLog);
fwrite(pBuffer, 1, nOutRead, stdout);
}
}
if( !_eof(hStdErrPipe[READ_HANDLE]) )
{
nOutRead = _read(hStdErrPipe[READ_HANDLE], pBuffer, sizeof pBuffer);
if(nOutRead)
{
fwrite(pBuffer, 1, nOutRead, pStdOutLog);
fwrite(pBuffer, 1, nOutRead, stderr);
}
}
GetExitCodeProcess(hProcess, &nExitCode);
}
}
fprintf(pStdOutLog, "\n# Process returned %d\n", nExitCode);
fclose(pStdOutLog);
return nExitCode;
}
#include <stdio.h>
#include <process.h>
#include <fcntl.h>
#include <windows.h>
#define LOG_PROCESS "some.exe"
#define STDOUT_LOG "stdout.log"
#define WRITE_HANDLE 1
#define READ_HANDLE 0
int main(int argc, char* argv[])
{
int hStdOutPipe[2], hStdErrPipe[2];
int hStdOut = _dup(_fileno(stdout));
if( _pipe(hStdOutPipe, 512, _O_TEXT | O_NOINHERIT) == -1
|| _dup2(hStdOutPipe[WRITE_HANDLE], _fileno(stdout)) )
return 1;
_close(hStdOutPipe[WRITE_HANDLE]);
int hStdErr = _dup(_fileno(stderr));
if( _pipe(hStdErrPipe, 512, _O_TEXT | O_NOINHERIT) == -1
|| _dup2(hStdErrPipe[WRITE_HANDLE], _fileno(stderr)) )
return 1;
_close(hStdErrPipe[WRITE_HANDLE]);
FILE* pStdOutLog = fopen(STDOUT_LOG, "a");
if(!pStdOutLog) return 1;
fprintf(pStdOutLog, "# ");
for(int i=0; i<argc; i++)
fprintf(pStdOutLog, "%s ", argv);
fprintf(pStdOutLog, "\n");
HANDLE hProcess = (HANDLE)_spawnv(P_NOWAIT, LOG_PROCESS, (const char* const*)&argv[0]);
if(INVALID_HANDLE_VALUE == hProcess)
{
fprintf(pStdOutLog, "# Can't spawn process.\n");
fclose(pStdOutLog);
return 1;
}
if( !_dup2(hStdOut, _fileno(stdout)) ) _close(hStdOut);
if( !_dup2(hStdErr, _fileno(stderr)) ) _close(hStdErr);
DWORD nExitCode = STILL_ACTIVE;
if(hProcess)
{
int nOutRead;
char pBuffer[128];
while( STILL_ACTIVE == nExitCode || !_eof(hStdOutPipe[READ_HANDLE]) || !_eof(hStdErrPipe[READ_HANDLE]) )
{
if( !_eof(hStdOutPipe[READ_HANDLE]) )
{
nOutRead = _read(hStdOutPipe[READ_HANDLE], pBuffer, sizeof pBuffer);
if(nOutRead)
{
fwrite(pBuffer, 1, nOutRead, pStdOutLog);
fwrite(pBuffer, 1, nOutRead, stdout);
}
}
if( !_eof(hStdErrPipe[READ_HANDLE]) )
{
nOutRead = _read(hStdErrPipe[READ_HANDLE], pBuffer, sizeof pBuffer);
if(nOutRead)
{
fwrite(pBuffer, 1, nOutRead, pStdOutLog);
fwrite(pBuffer, 1, nOutRead, stderr);
}
}
GetExitCodeProcess(hProcess, &nExitCode);
}
}
fprintf(pStdOutLog, "\n# Process returned %d\n", nExitCode);
fclose(pStdOutLog);
return nExitCode;
}
LOG_PROCESS - это имя исполняемого файла, лог вывода которого надо вести.
А в tee как сделано? (Просто из чистого любопытства, особенно разбираться в его исходниках нету ни времени ни желания).