Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. Мне нужно перенаправить стандартный вывод консоли в файл и/или пайп. Если быть точным, то мне надо что бы вывод консоли выводился в мемо. При этом что бы самой консоли не было видно. Перерыл пол инета, перепробовал множество примеров и ничего стоящего не нашел. Большинство примеров просто не работает или работает не так как хотелось бы. Может кто имеет готовый работающий пример или ссылку на оный.
Здравствуйте Oxy, Вы писали:
Oxy>Привет, всем!
Oxy>Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. Мне нужно перенаправить стандартный вывод консоли в файл и/или пайп. Если быть точным, то мне надо что бы вывод консоли выводился в мемо. При этом что бы самой консоли не было видно. Перерыл пол инета, перепробовал множество примеров и ничего стоящего не нашел. Большинство примеров просто не работает или работает не так как хотелось бы. Может кто имеет готовый работающий пример или ссылку на оный.
Убрать консоль — FreeConsole(). У меня работает. А вот SetStdHandle() почему-то не пашет..
BOOL CreateProcess(
LPCTSTR lpApplicationName, // name of executable module
LPTSTR lpCommandLine, // command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
BOOL bInheritHandles, // handle inheritance option
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // new environment block
LPCTSTR lpCurrentDirectory, // current directory name
LPSTARTUPINFO lpStartupInfo, // startup information
LPPROCESS_INFORMATION lpProcessInformation // process information
);
Чтоб не показывалось окно — юзай CREATE_NO_WINDOW для dwCreationFlags.
В lpStartupInfo засовываешь хэндлы консоли — я пометил, где
typedef struct _STARTUPINFO {
DWORD cb;
LPTSTR lpReserved;
LPTSTR lpDesktop;
LPTSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput; // вот куда перенаправляться будет
HANDLE hStdOutput; // вот куда перенаправляться будет
HANDLE hStdError; // вот куда перенаправляться будет} STARTUPINFO, *LPSTARTUPINFO;
Oxy>Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. Мне нужно перенаправить стандартный вывод консоли в файл и/или пайп. Если быть точным, то мне надо что бы вывод консоли выводился в мемо. При этом что бы самой консоли не было видно. Перерыл пол инета, перепробовал множество примеров и ничего стоящего не нашел. Большинство примеров просто не работает или работает не так как хотелось бы. Может кто имеет готовый работающий пример или ссылку на оный.
И не работает! В смысле файл stdout.txt пуст. На экран, правда, тоже ничего не выводится. Если сделать hFile наследуемым, лучше не становится. Если убрать CREATE_NO_WINDOW тоже. Неужели этот механизм не предназначен для файлов, а только для каналов?
SetStdHandle тоже не работает с файлами. Такое ощушение, что вызов игнорируется так как printf выводит на консоль.
SH>И не работает! В смысле файл stdout.txt пуст. На экран, правда, тоже ничего не выводится. Если сделать hFile наследуемым, лучше не становится. Если убрать CREATE_NO_WINDOW тоже. Неужели этот механизм не предназначен для файлов, а только для каналов?
A если si.dwFlags = STARTF_USESTDHANDLES добавить и разрешить наследование хэндлов дочерним процессом, заработает?
Здравствуйте Alex Fedotov, Вы писали:
AF>Здравствуйте SergH, Вы писали:
SH>>Здравствуйте Dutchman, Вы писали:
D>>>Гляди:
SH>>[skip]
SH>>Вот такой процесс-родитель:
SH>>
SH>>И не работает! В смысле файл stdout.txt пуст. На экран, правда, тоже ничего не выводится. Если сделать hFile наследуемым, лучше не становится. Если убрать CREATE_NO_WINDOW тоже. Неужели этот механизм не предназначен для файлов, а только для каналов?
AF>A если si.dwFlags = STARTF_USESTDHANDLES добавить и разрешить наследование хэндлов дочерним процессом, заработает?
Здравствуйте Alex Fedotov, Вы писали:
AF>A если si.dwFlags = STARTF_USESTDHANDLES добавить и разрешить наследование хэндлов дочерним процессом, заработает?
Спасибо, если сделать и то и то работает, по отдельности нет.
А про SetStdHandle ничего хорошего сказать не можешь?
А>>"разрешить наследование хэндлов дочерним процессом" не в тему, но я пробовал — не пашет!
SH>Надо не только разрешить наследование, но и сам хендл сделать наследуемым. Т.е.
SH>
Спасибо всем за помощь. Сделал как советовали. С тем примером printer, который предложил SergH, перенаправление в файл нормально работает. Но я попробовал такое же сделать с архиватором arj.exe и получил пустой файл. Тоже самое происходит с многими другими архиваторами: gzip, ha, Jar и т.д. Также перенаправление не работает с простеньким примером (который просто выводит несколько строчек) сделаным мной на TP 7.0. Хотя, например, с rar32.exe перенаправление в файл работает нормально.
В связи с эти возник вопрос. Можно ли сделать так что бы перенаправление работало для всех консольных приложений, в том числе и DOS-вских? Также как работает когда просто набрать в консоли
arj.exe > log.txt
При этом файл log.txt нормально создается и заполняется тем что выводит arj.exe.
Здравствуйте Oxy, Вы писали:
Oxy>В связи с эти возник вопрос. Можно ли сделать так что бы перенаправление работало для всех консольных приложений, в том числе и DOS-вских?
Может это поможет?
Q150956 INFO: Redirection Issues on Windows 95 MS-DOS Applications
Здравствуйте Alex Fedotov, Вы писали:
AF>Может это поможет?
AF>Q150956 INFO: Redirection Issues on Windows 95 MS-DOS Applications
Нет, это тоже не помогло. Наверное оно и не могло помочь так как там написано:
The following code sample demonstrates an intermediate stub application for redirecting 16-bit console based applications on Windows 95, Windows 98, and Windows Me.
А я работаю под вынь2к. И вообще я хотел создать редирект который бы работал под любой из ОС Win9x/ME/2k/XP.
Может кто то знает другие варианты? Помогите, плиз!
Здравствуйте Oxy, Вы писали:
Oxy>Здравствуйте Alex Fedotov, Вы писали:
AF>>Может это поможет?
AF>>Q150956 INFO: Redirection Issues on Windows 95 MS-DOS Applications
Oxy>Нет, это тоже не помогло. Наверное оно и не могло помочь так как там написано: Oxy>
Oxy>The following code sample demonstrates an intermediate stub application for redirecting 16-bit console based applications on Windows 95, Windows 98, and Windows Me.
Oxy>
Oxy>А я работаю под вынь2к. И вообще я хотел создать редирект который бы работал под любой из ОС Win9x/ME/2k/XP. Oxy>Может кто то знает другие варианты? Помогите, плиз!
Если ты перенаправляешь в файл, чем тебя не устраивает program.exe > text.txt? Подходит для всех ОС и всех программ. Понятно, что это менее гибко, но зато универсально и надёжно.
Здравствуйте SergH, Вы писали:
SH>Если ты перенаправляешь в файл, чем тебя не устраивает program.exe > text.txt? Подходит для всех ОС и всех программ. Понятно, что это менее гибко, но зато универсально и надёжно.
Да, наверное так и придется сделать. Но про перенаправление в файл я просто так написал, как про один из вариантов. На самом деле для меня лучше было бы перенаправлять ввод и вывод в пайп. Правда я нашел еще вариант — запустить прогу в своей консоли и читать посимвольно из нее.
Но все же хотелось бы иметь возможность управлять ДОС-ской прогой через StdIn и StdOut. Что бы вывод этой проги появлялся в моем окне синхронно, как генерирует его сама прога (например как в VC++ при компиляции), а не только после завершения работы. Не верю что MS не предусмотрела такой возможности. Наверно все же можно как-то это сделать.
Здравствуйте, Oxy, Вы писали:
Oxy>А я работаю под вынь2к. И вообще я хотел создать редирект который бы работал под любой из ОС Win9x/ME/2k/XP. Oxy>Может кто то знает другие варианты? Помогите, плиз!
Листая поиск по этой теме, я нашёл этот поток. Я тоже упёрся в проблему вывода в Win2k/XP (Win9x/ME — работает).
Прошло два года, может что-нибудь изменилось? Меня интереует код на API.
Привожу отрезок кода
Здравствуйте, вce!
Сегодня я проанилизировал некоторые примеры и пришёл к выоду что рершение задачи возможно разным путём. Не думаю, что кто-нибудь сможет оъяснить верность того или иного решения. Практика показала, что подобные задачи зачастую приходится решать путём подбора вариантов, ибо скудость информации от MS на эту тему безмерна. Привожу код работающий в 98 и 2000 Windows'ах.
Здравствуйте, Oxy, Вы писали:
Oxy>Привет, всем!
Oxy>Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. Мне нужно перенаправить стандартный вывод консоли в файл и/или пайп. Если быть точным, то мне надо что бы вывод консоли выводился в мемо. При этом что бы самой консоли не было видно. Перерыл пол инета, перепробовал множество примеров и ничего стоящего не нашел. Большинство примеров просто не работает или работает не так как хотелось бы. Может кто имеет готовый работающий пример или ссылку на оный.
#include <stdio.h>
int maint(int c, char** v){
FILE *out = _popen("your_exe_file.exe", "rt");
// дальше хоть обчитайся из "out"
// в конце ->
_pclose(out);
return 0;
}
Re: Перенаправление ввода-вывода консоли
От:
Аноним
Дата:
20.07.05 11:06
Оценка:
Здравствуйте, Oxy, Вы писали: Oxy>Привет, всем! Oxy>Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. ...
#include <stdio.h>
#include <windows.h>
#define BUFSIZE 4096
HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup,
hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup,
hInputFile, hStdout;
BOOL CreateChildProcess(VOID);
VOID WriteToPipe(VOID);
VOID ReadFromPipe(VOID);
VOID ErrorExit(LPTSTR);
VOID ErrMsg(LPTSTR, BOOL);
DWORD main(int argc, char *argv[])
{
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Get the handle to the current STDOUT.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
// Create a pipe for the child process's STDOUT. if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
ErrorExit("Stdout pipe creation failed\n");
// Create noninheritable read handle and close the inheritable read
// handle.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,
GetCurrentProcess(), &hChildStdoutRdDup , 0,
FALSE,
DUPLICATE_SAME_ACCESS);
if( !fSuccess )
ErrorExit("DuplicateHandle failed");
CloseHandle(hChildStdoutRd);
// Create a pipe for the child process's STDIN. if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
ErrorExit("Stdin pipe creation failed\n");
// Duplicate the write handle to the pipe so it is not inherited.
fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,
GetCurrentProcess(), &hChildStdinWrDup, 0,
FALSE, // not inherited
DUPLICATE_SAME_ACCESS);
if (! fSuccess)
ErrorExit("DuplicateHandle failed");
CloseHandle(hChildStdinWr);
// Now create the child process.
fSuccess = CreateChildProcess();
if (! fSuccess)
ErrorExit("Create process failed");
// Get a handle to the parent's input file. if (argc == 1)
ErrorExit("Please specify an input file");
hInputFile = CreateFile(argv[1], GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if (hInputFile == INVALID_HANDLE_VALUE)
ErrorExit("CreateFile failed\n");
// Write to pipe that is the standard input for a child process.
WriteToPipe();
// Read from pipe that is the standard output for child process.
ReadFromPipe();
return 0;
}
BOOL CreateChildProcess()
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
BOOL bFuncRetn = FALSE;
// Set up members of the PROCESS_INFORMATION structure.
ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
// Set up members of the STARTUPINFO structure.
ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = hChildStdoutWr;
siStartInfo.hStdOutput = hChildStdoutWr;
siStartInfo.hStdInput = hChildStdinRd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
// Create the child process.
bFuncRetn = CreateProcess(NULL,
"child", // command line
NULL, // process security attributes
NULL, // primary thread security attributes
TRUE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&siStartInfo, // STARTUPINFO pointer
&piProcInfo); // receives PROCESS_INFORMATION if (bFuncRetn == 0)
ErrorExit("CreateProcess failed");
else
{
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
return bFuncRetn;
}
}
VOID WriteToPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
// Read from a file and write its contents to a pipe. for (;;)
{
if (! ReadFile(hInputFile, chBuf, BUFSIZE, &dwRead, NULL) ||
dwRead == 0) break;
if (! WriteFile(hChildStdinWrDup, chBuf, dwRead,
&dwWritten, NULL)) break;
}
// Close the pipe handle so the child process stops reading. if (! CloseHandle(hChildStdinWrDup))
ErrorExit("Close pipe failed");
}
VOID ReadFromPipe(VOID)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
// Close the write end of the pipe before reading from the
// read end of the pipe. if (!CloseHandle(hChildStdoutWr))
ErrorExit("CloseHandle failed");
// Read output from the child process, and write to parent's STDOUT. for (;;)
{
if( !ReadFile( hChildStdoutRdDup, chBuf, BUFSIZE, &dwRead,
NULL) || dwRead == 0) break;
if (! WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL))
break;
}
}
VOID ErrorExit (LPTSTR lpszMessage)
{
fprintf(stderr, "%s\n", lpszMessage);
ExitProcess(0);
}
The following is the code for the child process. It uses the inherited handles for STDIN and STDOUT to access the pipe created by the parent. The parent process reads from its input file and writes the information to a pipe. The child receives text through the pipe using STDIN and writes to the pipe using STDOUT. The parent reads from the read end of the pipe and displays the information to its STDOUT.
#include <windows.h>
#define BUFSIZE 4096
VOID main(VOID)
{
CHAR chBuf[BUFSIZE];
DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout;
BOOL fSuccess;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hStdin = GetStdHandle(STD_INPUT_HANDLE);
if ((hStdout == INVALID_HANDLE_VALUE) ||
(hStdin == INVALID_HANDLE_VALUE))
ExitProcess(1);
for (;;)
{
// Read from standard input.
fSuccess = ReadFile(hStdin, chBuf, BUFSIZE, &dwRead, NULL);
if (! fSuccess || dwRead == 0)
break;
// Write to standard output.
fSuccess = WriteFile(hStdout, chBuf, dwRead, &dwWritten, NULL);
if (! fSuccess)
break;
}
}