Иной раз в процессе разработки ПО или же автоматизации каких-либо процессов сталкиваюсь с необходимостью использовать консольные (без графического интерфейса) версии программ и утилит в качестве вспомогательных по отношению к «главному» приложению (которое вполне себе имеет GUI). Ниже я напишу шпаргалку (больше для самого себя) по редиректу вывода из командной строки в текстовое поле Memo.

Процедура имеет следующий вид:

void cmdToMemo(String App)
{

#define READ_BUFFER_SIZE 1024
String AppName = App;
SECURITY_ATTRIBUTES Security;
HANDLE ReadPipe, WritePipe;
STARTUPINFO Start;
TProcessInformation ProcessInfo;
char *Buffer, Data;
DWORD BytesRead, Apprunning;
int Result, DataSize;

Security.nLength = sizeof(TSecurityAttributes);
Security.bInheritHandle = true;
Security.lpSecurityDescriptor = NULL;

if (CreatePipe(&ReadPipe, &WritePipe, &Security, 0))
{

Buffer = new char[READ_BUFFER_SIZE + 1];
memset(&Start, 0, sizeof(Start));
Start.cb = sizeof(Start) ;
Start.hStdOutput = WritePipe;
Start.hStdInput = ReadPipe;
Start.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
Start.wShowWindow = SW_HIDE;

if (CreateProcess(NULL, AppName.c_str(), &Security, &Security, true, NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, NULL, NULL, &Start, &ProcessInfo))
{

do
{

Apprunning = WaitForSingleObject(ProcessInfo.hProcess, 100);
Application->ProcessMessages();
do
{

Result = PeekNamedPipe(ReadPipe, NULL, 0, NULL, (LPDWORD) &DataSize, NULL);
if ((Result) && (DataSize))
{

if (DataSize > READ_BUFFER_SIZE) DataSize = READ_BUFFER_SIZE;
{

ReadFile(ReadPipe, Buffer, DataSize, &BytesRead, NULL);

}

Buffer[BytesRead] = 0;
OemToAnsi(Buffer, Buffer);
MainForm->Memo->Text = MainForm->Memo->Text + (AnsiString) Buffer;

}

}

while ((Result) && (DataSize));

}
while (Apprunning == WAIT_TIMEOUT);
while ((Result) && (DataSize));

}
delete [] Buffer;
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ReadPipe);
CloseHandle(WritePipe);

}
return;

}

В главной функции main я делаю вызов вышеописанной процедуры и в качестве входного параметра передаю строку, например, ipconfig.exe

cmdToMemo(″ipconfig.exe″);

Если все сделано правильно, то вы увидите соответствующий вывод: