Перенаправление ввода-вывода консоли
От: Oxy  
Дата: 09.05.02 11:48
Оценка:
Привет, всем!

Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. Мне нужно перенаправить стандартный вывод консоли в файл и/или пайп. Если быть точным, то мне надо что бы вывод консоли выводился в мемо. При этом что бы самой консоли не было видно. Перерыл пол инета, перепробовал множество примеров и ничего стоящего не нашел. Большинство примеров просто не работает или работает не так как хотелось бы. Может кто имеет готовый работающий пример или ссылку на оный.
Re: Перенаправление ввода-вывода консоли
От: SergH Россия  
Дата: 09.05.02 12:29
Оценка:
Здравствуйте Oxy, Вы писали:

Oxy>Привет, всем!


Oxy>Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. Мне нужно перенаправить стандартный вывод консоли в файл и/или пайп. Если быть точным, то мне надо что бы вывод консоли выводился в мемо. При этом что бы самой консоли не было видно. Перерыл пол инета, перепробовал множество примеров и ничего стоящего не нашел. Большинство примеров просто не работает или работает не так как хотелось бы. Может кто имеет готовый работающий пример или ссылку на оный.


Убрать консоль — FreeConsole(). У меня работает. А вот SetStdHandle() почему-то не пашет..
Делай что должно, и будь что будет
Re: Перенаправление ввода-вывода консоли
От: Хитрик Денис Россия RSDN
Дата: 09.05.02 12:39
Оценка:
Здравствуйте Oxy, Вы писали:

Здесь
Автор: genesys
Дата: 12.09.01
не то?
Правила нашего с вами форума.
Как правильно задавать вопросы. © 2001 by Eric S. Raymond; перевод: © 2002 Валерий Кравчук.
Re: Перенаправление ввода-вывода консоли
От: Dutchman Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.05.02 12:40
Оценка: 5 (1)
Здравствуйте Oxy, Вы писали:

Гляди:

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>Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. Мне нужно перенаправить стандартный вывод консоли в файл и/или пайп. Если быть точным, то мне надо что бы вывод консоли выводился в мемо. При этом что бы самой консоли не было видно. Перерыл пол инета, перепробовал множество примеров и ничего стоящего не нашел. Большинство примеров просто не работает или работает не так как хотелось бы. Может кто имеет готовый работающий пример или ссылку на оный.
Re[2]: Перенаправление ввода-вывода консоли
От: SergH Россия  
Дата: 09.05.02 14:19
Оценка:
Здравствуйте Dutchman, Вы писали:

D>Гляди:


[skip]

Вот такой процесс-родитель:

#include <windows.h>

void main()
{
    HANDLE hFile;
    
    hFile = CreateFile(
                "stdout.txt",
                GENERIC_WRITE | GENERIC_READ, 
                FILE_SHARE_READ | FILE_SHARE_WRITE, 
                NULL,
                OPEN_ALWAYS,
                0,
                NULL);

    SetFilePointer(hFile, 0, NULL, FILE_END);

    STARTUPINFO si = {sizeof(STARTUPINFO)};

    si.hStdOutput = hFile;

    PROCESS_INFORMATION pi;

    CreateProcess(NULL, "printer.exe", NULL, NULL, FALSE, CREATE_NO_WINDOW, 0, 0, &si, &pi);

    // MessageBox(NULL, "Press OK", "", MB_OK);
    CloseHandle(hFile);
}


Запускает такого потомка:

#include <stdio.h>

void main()
{
    printf("Hello, World");
}


И не работает! В смысле файл stdout.txt пуст. На экран, правда, тоже ничего не выводится. Если сделать hFile наследуемым, лучше не становится. Если убрать CREATE_NO_WINDOW тоже. Неужели этот механизм не предназначен для файлов, а только для каналов?

SetStdHandle тоже не работает с файлами. Такое ощушение, что вызов игнорируется так как printf выводит на консоль.
Делай что должно, и будь что будет
Re[3]: Перенаправление ввода-вывода консоли
От: Alex Fedotov США  
Дата: 09.05.02 14:59
Оценка: 8 (1)
Здравствуйте SergH, Вы писали:

SH>Здравствуйте Dutchman, Вы писали:


D>>Гляди:


SH>[skip]


SH>Вот такой процесс-родитель:


SH>
SH>#include <windows.h>

SH>void main()
SH>{
SH>    HANDLE hFile;
SH>    
SH>    hFile = CreateFile(
SH>                "stdout.txt",
SH>                GENERIC_WRITE | GENERIC_READ, 
SH>                FILE_SHARE_READ | FILE_SHARE_WRITE, 
SH>                NULL,
SH>                OPEN_ALWAYS,
SH>                0,
SH>                NULL);

SH>    SetFilePointer(hFile, 0, NULL, FILE_END);

SH>    STARTUPINFO si = {sizeof(STARTUPINFO)};

SH>    si.hStdOutput = hFile;

SH>    PROCESS_INFORMATION pi;

SH>    CreateProcess(NULL, "printer.exe", NULL, NULL, FALSE, CREATE_NO_WINDOW, 0, 0, &si, &pi);

SH>    // MessageBox(NULL, "Press OK", "", MB_OK);
SH>    CloseHandle(hFile);
SH>}
SH>


SH>Запускает такого потомка:


SH>
SH>#include <stdio.h>

SH>void main()
SH>{
SH>    printf("Hello, World");
SH>}
SH>


SH>И не работает! В смысле файл stdout.txt пуст. На экран, правда, тоже ничего не выводится. Если сделать hFile наследуемым, лучше не становится. Если убрать CREATE_NO_WINDOW тоже. Неужели этот механизм не предназначен для файлов, а только для каналов?


A если si.dwFlags = STARTF_USESTDHANDLES добавить и разрешить наследование хэндлов дочерним процессом, заработает?
-- Alex Fedotov
Re[4]: Перенаправление ввода-вывода консоли
От: Алекс Россия http://wise-orm.com
Дата: 09.05.02 15:06
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>Здравствуйте SergH, Вы писали:


SH>>Здравствуйте Dutchman, Вы писали:


D>>>Гляди:


SH>>[skip]


SH>>Вот такой процесс-родитель:


SH>>
SH>>#include <windows.h>

SH>>void main()
SH>>{
SH>>    HANDLE hFile;
SH>>    
SH>>    hFile = CreateFile(
SH>>                "stdout.txt",
SH>>                GENERIC_WRITE | GENERIC_READ, 
SH>>                FILE_SHARE_READ | FILE_SHARE_WRITE, 
SH>>                NULL,
SH>>                OPEN_ALWAYS,
SH>>                0,
SH>>                NULL);

SH>>    SetFilePointer(hFile, 0, NULL, FILE_END);

SH>>    STARTUPINFO si = {sizeof(STARTUPINFO)};

SH>>    si.hStdOutput = hFile;

SH>>    PROCESS_INFORMATION pi;

SH>>    CreateProcess(NULL, "printer.exe", NULL, NULL, FALSE, CREATE_NO_WINDOW, 0, 0, &si, &pi);

SH>>    // MessageBox(NULL, "Press OK", "", MB_OK);
SH>>    CloseHandle(hFile);
SH>>}
SH>>


SH>>Запускает такого потомка:


SH>>
SH>>#include <stdio.h>

SH>>void main()
SH>>{
SH>>    printf("Hello, World");
SH>>}
SH>>


SH>>И не работает! В смысле файл stdout.txt пуст. На экран, правда, тоже ничего не выводится. Если сделать hFile наследуемым, лучше не становится. Если убрать CREATE_NO_WINDOW тоже. Неужели этот механизм не предназначен для файлов, а только для каналов?


AF>A если si.dwFlags = STARTF_USESTDHANDLES добавить и разрешить наследование хэндлов дочерним процессом, заработает?


Даже так не работает:
    STARTUPINFO si = {sizeof(STARTUPINFO)};
    GetStartupInfo(&si);
    si.dwFlags = STARTF_USESTDHANDLES;
    si.hStdOutput = hFile;

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));

    if (CreateProcess(NULL, "rs1.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE/*CREATE_NO_WINDOW*/, 0, 0, &si, &pi)){
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    }
    else{
    int err = GetLastError();
    printf("Error code %d",err);
    }

"разрешить наследование хэндлов дочерним процессом" не в тему, но я пробовал — не пашет!
Re[4]: Перенаправление ввода-вывода консоли
От: SergH Россия  
Дата: 09.05.02 16:01
Оценка:
Здравствуйте Alex Fedotov, Вы писали:

AF>A если si.dwFlags = STARTF_USESTDHANDLES добавить и разрешить наследование хэндлов дочерним процессом, заработает?


Спасибо, если сделать и то и то работает, по отдельности нет.

А про SetStdHandle ничего хорошего сказать не можешь?
Делай что должно, и будь что будет
Перенаправление ввода-вывода консоли
От: SergH Россия  
Дата: 09.05.02 16:05
Оценка: 10 (1)
#Имя: FAQ.winapi.consoleinout
Здравствуйте Алекс, Вы писали:

А>Даже так не работает:

А>
А>    STARTUPINFO si = {sizeof(STARTUPINFO)};
А>    GetStartupInfo(&si);
А>    si.dwFlags = STARTF_USESTDHANDLES;
А>    si.hStdOutput = hFile;

А>    PROCESS_INFORMATION pi;
А>    ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));

А>    if (CreateProcess(NULL, "rs1.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE/*CREATE_NO_WINDOW*/, 0, 0, &si, &pi)){
А>    CloseHandle(pi.hThread);
А>    CloseHandle(pi.hProcess);
А>    }
А>    else{
А>    int err = GetLastError();
А>    printf("Error code %d",err);
А>    }
А>

А>"разрешить наследование хэндлов дочерним процессом" не в тему, но я пробовал — не пашет!

Надо не только разрешить наследование, но и сам хендл сделать наследуемым. Т.е.

void main()
{
    HANDLE hFile;

    SECURITY_ATTRIBUTES sa;

    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;    
    sa.lpSecurityDescriptor = NULL;
    
    hFile = CreateFile(
                "stdout.txt",
                GENERIC_WRITE | GENERIC_READ, 
                FILE_SHARE_READ | FILE_SHARE_WRITE, 
                &sa,
                OPEN_ALWAYS,
                0,
                NULL);

    SetFilePointer(hFile, 0, NULL, FILE_END);

    STARTUPINFO si = {sizeof(STARTUPINFO)};

    si.hStdOutput = hFile;
    si.dwFlags    = STARTF_USESTDHANDLES;

    PROCESS_INFORMATION pi;

    CreateProcess(NULL, "printer.exe", NULL, NULL, TRUE ,0, 0, 0, &si, &pi);

    CloseHandle(hFile);
}


У меня в таком виде работает.
Делай что должно, и будь что будет
Re[5]: Перенаправление ввода-вывода консоли
От: SergH Россия  
Дата: 09.05.02 16:26
Оценка:
Здравствуйте SergH, Вы писали:

Кстати, для токого потомка тоже работает:

int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    printf("Hello World!\n");
    return 0;
}
Делай что должно, и будь что будет
Re[6]: Перенаправление ввода-вывода консоли
От: Алекс Россия http://wise-orm.com
Дата: 09.05.02 17:10
Оценка:
Здравствуйте SergH, Вы писали:

SH>Здравствуйте Алекс, Вы писали:


А>>Даже так не работает:

А>>
А>>    STARTUPINFO si = {sizeof(STARTUPINFO)};
А>>    GetStartupInfo(&si);
А>>    si.dwFlags = STARTF_USESTDHANDLES;
А>>    si.hStdOutput = hFile;

А>>    PROCESS_INFORMATION pi;
А>>    ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));

А>>    if (CreateProcess(NULL, "rs1.exe", NULL, NULL, FALSE, CREATE_NEW_CONSOLE/*CREATE_NO_WINDOW*/, 0, 0, &si, &pi)){
А>>    CloseHandle(pi.hThread);
А>>    CloseHandle(pi.hProcess);
А>>    }
А>>    else{
А>>    int err = GetLastError();
А>>    printf("Error code %d",err);
А>>    }
А>>

А>>"разрешить наследование хэндлов дочерним процессом" не в тему, но я пробовал — не пашет!

SH>Надо не только разрешить наследование, но и сам хендл сделать наследуемым. Т.е.


SH>
SH>void main()
SH>{
SH>    HANDLE hFile;

SH>    SECURITY_ATTRIBUTES sa;

SH>    sa.nLength = sizeof(sa);
SH>    sa.bInheritHandle = TRUE;    
SH>    sa.lpSecurityDescriptor = NULL;
SH>    
SH>    hFile = CreateFile(
SH>                "stdout.txt",
SH>                GENERIC_WRITE | GENERIC_READ, 
SH>                FILE_SHARE_READ | FILE_SHARE_WRITE, 
SH>                &sa,
SH>                OPEN_ALWAYS,
SH>                0,
SH>                NULL);

SH>    SetFilePointer(hFile, 0, NULL, FILE_END);

SH>    STARTUPINFO si = {sizeof(STARTUPINFO)};

SH>    si.hStdOutput = hFile;
SH>    si.dwFlags    = STARTF_USESTDHANDLES;

SH>    PROCESS_INFORMATION pi;

SH>    CreateProcess(NULL, "printer.exe", NULL, NULL, TRUE ,0, 0, 0, &si, &pi);

SH>    CloseHandle(hFile);
SH>}
SH>


SH>У меня в таком виде работает.


Точно, у меня тоже заработало.
Только если указать флаг CREATE_NEW_CONSOLE — не пашет!
Re: Перенаправление ввода-вывода консоли
От: Oxy  
Дата: 09.05.02 19:14
Оценка:
Спасибо всем за помощь. Сделал как советовали. С тем примером printer, который предложил SergH, перенаправление в файл нормально работает. Но я попробовал такое же сделать с архиватором arj.exe и получил пустой файл. Тоже самое происходит с многими другими архиваторами: gzip, ha, Jar и т.д. Также перенаправление не работает с простеньким примером (который просто выводит несколько строчек) сделаным мной на TP 7.0. Хотя, например, с rar32.exe перенаправление в файл работает нормально.
В связи с эти возник вопрос. Можно ли сделать так что бы перенаправление работало для всех консольных приложений, в том числе и DOS-вских? Также как работает когда просто набрать в консоли
arj.exe > log.txt
При этом файл log.txt нормально создается и заполняется тем что выводит arj.exe.
Re[2]: Перенаправление ввода-вывода консоли
От: Alex Fedotov США  
Дата: 09.05.02 19:20
Оценка:
Здравствуйте Oxy, Вы писали:

Oxy>В связи с эти возник вопрос. Можно ли сделать так что бы перенаправление работало для всех консольных приложений, в том числе и DOS-вских?


Может это поможет?

Q150956 INFO: Redirection Issues on Windows 95 MS-DOS Applications
-- Alex Fedotov
Re[3]: Перенаправление ввода-вывода консоли
От: Oxy  
Дата: 10.05.02 17:28
Оценка:
Здравствуйте 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.
Может кто то знает другие варианты? Помогите, плиз!
Re[4]: Перенаправление ввода-вывода консоли
От: SergH Россия  
Дата: 10.05.02 17:36
Оценка:
Здравствуйте 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? Подходит для всех ОС и всех программ. Понятно, что это менее гибко, но зато универсально и надёжно.
Делай что должно, и будь что будет
Re[5]: Перенаправление ввода-вывода консоли
От: Oxy  
Дата: 10.05.02 17:54
Оценка:
Здравствуйте SergH, Вы писали:

SH>Если ты перенаправляешь в файл, чем тебя не устраивает program.exe > text.txt? Подходит для всех ОС и всех программ. Понятно, что это менее гибко, но зато универсально и надёжно.


Да, наверное так и придется сделать. Но про перенаправление в файл я просто так написал, как про один из вариантов. На самом деле для меня лучше было бы перенаправлять ввод и вывод в пайп. Правда я нашел еще вариант — запустить прогу в своей консоли и читать посимвольно из нее.
Но все же хотелось бы иметь возможность управлять ДОС-ской прогой через StdIn и StdOut. Что бы вывод этой проги появлялся в моем окне синхронно, как генерирует его сама прога (например как в VC++ при компиляции), а не только после завершения работы. Не верю что MS не предусмотрела такой возможности. Наверно все же можно как-то это сделать.
Re[6]: Перенаправление ввода-вывода консоли
От: ua1zcl Россия www.alexklm.ru
Дата: 21.05.04 13:00
Оценка:
Здравствуйте, Oxy, Вы писали:

Oxy>А я работаю под вынь2к. И вообще я хотел создать редирект который бы работал под любой из ОС Win9x/ME/2k/XP.

Oxy>Может кто то знает другие варианты? Помогите, плиз!
Листая поиск по этой теме, я нашёл этот поток. Я тоже упёрся в проблему вывода в Win2k/XP (Win9x/ME — работает).
Прошло два года, может что-нибудь изменилось? Меня интереует код на API.
Привожу отрезок кода



static bool RunProcess(PVOID pv)
{
 if(!pRcvBuf)pRcvBuf= new char[100];
 if(!pTsmBuf)pTsmBuf= new char[100];
 bool fSuccess;
 int iFailures=0;
 
 if(ptl) 
 { 
  sprintf(str,"Running %s   '%s' { %s} for {%s}\r\n",
             ptl->szTlType[0]?ptl->szTlType:"CommandLine tool",
                 ptl->szTlAlias[0]?ptl->szTlAlias:"",
                 pszThisToolFPath,pszTargetFile);
 }
 else sprintf(str,"Running...  {tool: %s} for {%s}\r\n",pszThisToolFPath,pszTargetFile);
 Lm(str);

 dwNbytesRead=0; dwReadSoFar=0; dwWritn=0;
 DWORD dwRes;
 DWORD dwRead=1;
 bool bRead=1,bRes=0;
 SECURITY_ATTRIBUTES sa;

 if(sg.uOsVersion==W2000 || sg.uOsVersion==WXP || sg.uOsVersion==WNT4)
 {
  SECURITY_DESCRIPTOR sd={0};
  SECURITY_DESCRIPTOR_CONTROL sc={0};
  DWORD dwRevision=1;
  BOOL b=GetSecurityDescriptorControl(&sd,&sc,&dwRevision);
  //if(!b)Gle();
 }
 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
 sa.lpSecurityDescriptor = NULL;
 sa.bInheritHandle = TRUE;

 hChildsInpPipe=0; hMyOutPipe=0; hChildsOutPipe=0; hMyReadPipe=0;
 OVERLAPPED ov={0};
 memset(&pi,0,sizeof pi);
 STARTUPINFO si={0};
 BOOL bProc;
 HANDLE hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 HANDLE hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
 HANDLE hCurProc=GetCurrentProcess();

 memset(&si, 0, sizeof(STARTUPINFO));

 if(!CreatePipe(&hMyReadPipe, &hChildsOutPipe, &sa,0x10000)){ goto end;}
 if(!CreatePipe(&hChildsInpPipe, &hMyOutPipe, &sa,0x10000)){ goto end;}

  // Set a write handle to the pipe to be STDOUT.
 if(!SetStdHandle(STD_OUTPUT_HANDLE, hChildsOutPipe))
  { Mbox("Redirecting STDOUT failed");  goto end;}
   // Set a read handle to the pipe to be STDIN.
 if(!SetStdHandle(STD_INPUT_HANDLE, hChildsInpPipe))
  {  Mbox("Redirecting Stdin failed");  goto end;}

 si.cb = sizeof(STARTUPINFO);
 si.dwFlags = STARTF_USESTDHANDLES;


  fSuccess = DuplicateHandle(hCurProc,hChildsOutPipe,
                             hCurProc, &hChildsOutPipeDup,0,
                             FALSE,DUPLICATE_SAME_ACCESS);
  if( !fSuccess ) Mbox("DuplicateHandle failed");

  fSuccess = DuplicateHandle(hCurProc,hChildsInpPipe,
                             hCurProc, &hChildsInpPipeDup,0,
                             FALSE,DUPLICATE_SAME_ACCESS);
  if( !fSuccess ) Mbox("DuplicateHandle failed");

 //si.hStdError = hChildsOutPipe;
 //si.hStdInput = hChildsInpPipe;
 //si.hStdOutput = hChildsOutPipe;/
 si.hStdError = hChildsOutPipeDup;
 si.hStdInput = hChildsInpPipeDup;
 si.hStdOutput =hChildsOutPipeDup;
 si.wShowWindow=SW_HIDE;
 si.dwFillAttribute=0;//BACKGROUND_BLUE|FOREGROUND_GREEN;
 si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;//|STARTF_USEFILLATTRIBUTE;//    |


 SetCurrentDirectory(pszCurrDir);// Чтобы компилятор знал откуда плясать


 #ifdef DBUG
 SaveShortFile("_CmdLineReal.txt",pszFullCmdLine,strlen(pszFullCmdLine));
 #endif

 bProc=CreateProcess(NULL,pszFullCmdLine,0,0,TRUE,CREATE_SUSPENDED|CREATE_NO_WINDOW,0,0, &si, &pi);
 if(!bProc || (!pi.hProcess || !pi.hThread || !pi.dwProcessId || !pi.dwThreadId))
 { Mbox("No Process created"); Gle(); goto end;}

 CloseHandle(hChildsOutPipeDup); hChildsOutPipeDup=0;
 CloseHandle(hChildsInpPipeDup); hChildsInpPipeDup=0;
 CloseHandle(hChildsOutPipe); hChildsOutPipe=0;
 CloseHandle(hChildsInpPipe); hChildsInpPipe=0;
 
 dwTicksStarted=GetTickCount();
 
 dwRes=ResumeThread(pi.hThread);
 //sprintf(str,"ResumeThread return %d\r\n",dwRes); Lm(str);
 SetLastError(0);
 
 while((bRead && dwRead) || iFailures < 10)
 { dwRead=0;
   dwTicksLastRead=GetTickCount();
   bRead=ReadFile(hMyReadPipe,pRcvBuf+dwNbytesRead,2,&dwRead,0);

   if(bRead && dwRead)
   { dwNbytesRead+=dwRead;  
     if( dwNbytesRead+1>=50)
     { *(pRcvBuf+dwNbytesRead)=0; Lm(pRcvBuf); 
       dwReadSoFar+=dwNbytesRead; dwNbytesRead=0;
     }
   }
   else iFailures++;
    //else Gle();
 }
 //sprintf(str,"dwReadSoFar %d\r\n",dwReadSoFar); Lm(str);
 bRes=CompleteReading();
 SaveShortFile("_pszLe.txt",pszLe,iCurErrStrlen);
 if(ptl)FindAndAddWarnsErrorMessage(ptl,pv);

end:
 if(hChildsInpPipe)CloseHandle(hChildsInpPipe);
 if(hMyOutPipe)CloseHandle(hMyOutPipe);
 if(hChildsOutPipe)CloseHandle(hChildsOutPipe);
 if(hMyReadPipe)CloseHandle(hMyReadPipe);
 if(ov.hEvent)CloseHandle(ov.hEvent);
 SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
 SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
 dwTicksFinished=GetTickCount();
 return bRes;
}
Александр
Re[7]: Перенаправление ввода-вывода консоли
От: ua1zcl Россия www.alexklm.ru
Дата: 21.05.04 18:34
Оценка:
Здравствуйте, вce!
Сегодня я проанилизировал некоторые примеры и пришёл к выоду что рершение задачи возможно разным путём. Не думаю, что кто-нибудь сможет оъяснить верность того или иного решения. Практика показала, что подобные задачи зачастую приходится решать путём подбора вариантов, ибо скудость информации от MS на эту тему безмерна. Привожу код работающий в 98 и 2000 Windows'ах.

/////////////////////////////////////////////////////////////////////////////////
static void EnsureChildProcDied(void);
static PROCESS_INFORMATION pi;


static bool RunProcess(PVOID pv)
{
 if(!pRcvBuf)pRcvBuf= new char[100];
 if(!pTsmBuf)pTsmBuf= new char[100];
 HANDLE hChildsInpPipe=0,hMyOutPipe=0;
 HANDLE hChildsOutPipe=0,hMyInpPipe=0;
 bool fSuccess;
 int iFailures=0;

 if(ptl)
 {
  sprintf(str,"Running %s   '%s' { %s} for {%s}\r\n",
             ptl->szTlType[0]?ptl->szTlType:"CommandLine tool",
                 ptl->szTlAlias[0]?ptl->szTlAlias:"",
                 pszThisToolFPath,pszTargetFile);
 }
 else sprintf(str,"Running...  {tool: %s} for {%s}\r\n",pszThisToolFPath,pszTargetFile);
 Lm(str);

 dwNbytesRead=0; dwReadSoFar=0; dwWritn=0;
 DWORD dwRes;
 DWORD dwRead=1;
 bool bRead=1,bRes=0;
 PVOID psd = NULL;
 LPSECURITY_ATTRIBUTES psa=0;

 if(sg.uOsVersion==W2000 || sg.uOsVersion==WXP || sg.uOsVersion==WNT4)
 {
  assert(psd = GlobalAlloc(GPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
  assert(InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION));
  assert(SetSecurityDescriptorDacl(psd, -1, 0, 0));

  psa = (LPSECURITY_ATTRIBUTES)::GlobalAlloc(GPTR, sizeof(SECURITY_ATTRIBUTES));
  psa->nLength = sizeof(SECURITY_ATTRIBUTES);
  psa->lpSecurityDescriptor = psd;
  psa->bInheritHandle = TRUE;
 }

 memset(&pi,0,sizeof pi);
 STARTUPINFO si={0};
 BOOL bProc;
 HANDLE hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
 HANDLE hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
 HANDLE hCurProc=GetCurrentProcess();

 memset(&si, 0, sizeof(STARTUPINFO));

 if(!CreatePipe(&hMyInpPipe, &hChildsOutPipe, psa,10000)){ goto end;}
 if(!CreatePipe(&hChildsInpPipe, &hMyOutPipe, psa,10000)){ goto end;}

 si.cb = sizeof(STARTUPINFO);
 si.dwFlags = STARTF_USESTDHANDLES;

 si.hStdError = hChildsOutPipe;
 si.hStdInput = hChildsInpPipe;
 si.hStdOutput = hChildsOutPipe;

 si.wShowWindow=SW_HIDE;
 si.dwFillAttribute=0;//BACKGROUND_BLUE|FOREGROUND_GREEN;
 si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;//|STARTF_USEFILLATTRIBUTE;//    |

 SetCurrentDirectory(pszCurrDir);// Чтобы компилятор знал откуда плясать

 #ifdef DBUG
 SaveShortFile("_CmdLineReal.txt",pszFullCmdLine,strlen(pszFullCmdLine));
 #endif


 SetStdHandle(STD_OUTPUT_HANDLE,hChildsOutPipe);
 SetStdHandle(STD_ERROR_HANDLE,hChildsOutPipe);
 SetStdHandle(STD_INPUT_HANDLE,hChildsInpPipe);

 bProc=CreateProcess(NULL,pszFullCmdLine,0,psa,TRUE,CREATE_SUSPENDED,0,0, &si, &pi);//|CREATE_NEW_CONSOLE
 if(!bProc || (!pi.hProcess || !pi.hThread || !pi.dwProcessId || !pi.dwThreadId))
 { Mbox("No Process created"); Gle(); goto end;}

 if(hChildsOutPipe)CloseHandle(hChildsOutPipe); hChildsOutPipe=0;
 if(hChildsInpPipe)CloseHandle(hChildsInpPipe); hChildsInpPipe=0;

 dwTicksStarted=GetTickCount();

 dwRes=ResumeThread(pi.hThread);
 //sprintf(str,"ResumeThread return %d\r\n",dwRes); Lm(str);
 SetLastError(0);

 while((bRead && dwRead) || iFailures < 10)
 {
  dwRead=0;
  bRead=ReadFile(hMyInpPipe,pRcvBuf+dwNbytesRead,1,&dwRead,0);

   if(bRead && dwRead)
   { dwNbytesRead+=dwRead;
     if( dwNbytesRead+1>=50)
     { *(pRcvBuf+dwNbytesRead)=0; Lm(pRcvBuf);
       dwReadSoFar+=dwNbytesRead; dwNbytesRead=0;
     }
   }
   else iFailures++;
 }
 //sprintf(str,"dwReadSoFar %d\r\n",dwReadSoFar); Lm(str);
 bRes=CompleteReading();
 #ifdef DBUG
 SaveShortFile("_pszLe.txt",pszLe,iCurErrStrlen);
 #endif
 if(ptl)FindAndAddWarnsErrorMessage(ptl,pv);

end:
 if(hChildsInpPipe)CloseHandle(hChildsInpPipe);
 if(hMyOutPipe)CloseHandle(hMyOutPipe);
 if(hChildsOutPipe)CloseHandle(hChildsOutPipe);
 if(hMyInpPipe)CloseHandle(hMyInpPipe);

 SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
 SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
 //CloseHandle(pi.hThread);
 // Cleanup memory allocation
 if(psa)GlobalFree(psa);
 if(psd)GlobalFree(psd);
 EnsureChildProcDied();
 dwTicksFinished=GetTickCount();
 return bRes;
}
////////////////////////////////////////////////////////////////////////////////

static void EnsureChildProcDied(void)
{
 if(pi.hProcess && pi.dwProcessId &&  GetProcessVersion(pi.dwProcessId))
 {
  DWORD dwRes=WaitForInputIdle(pi.hProcess,500);
  BOOL bTermRes=TerminateProcess(pi.hProcess,0);
  if(!bTermRes)Gle();
  else *zd.pbCompiling=0;
 }
}
////////////////////////////////////////////////////////////////////////////////
Александр
Re: Перенаправление ввода-вывода консоли
От: Аноним  
Дата: 25.04.05 21:53
Оценка:
Здравствуйте, 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>Помогите, пожалуйста, с перенаправлением ввода-вывода консоли. ...

Ссылка в MSDN'e:
ms-help://MS.MSDNQTR.2004JUL.1033/dllproc/base/creating_a_child_process_with_redirected_input_and_output.htm
код:
The following is the code for the parent process. It takes a single command-line argument: the name of a text file.
#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; 
   } 
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.