Пользователь
Регистрация: 30.06.2009
Сообщений: 18
|
Запуск и чтение данных из консоли
Нужно запустить консольную программу и считывать по таймеру ее вывод. Вопрос поднимался неоднократно и в нете много инфы по этой теме есть, но я никак немогу понять, почему у меня не считываются данные.
Объявление переменных:
Цитата:
bool Started = false;
unsigned long pExit;
unsigned long bread;
unsigned long avail;
char buf[1024];
HANDLE newstdin,newstdout,read_stdout,writ e_stdin;
HANDLE TerminateHandle;
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
PROCESS_INFORMATION pi;
STARTUPINFO si;
typedef struct
{
HANDLE hProcess;
HWND hWnd;
}Params;
|
Функции запуска и считывания:
Цитата:
void StartPipe(String app_spawn)
{
try
{
if (IsWinNT())
{
InitializeSecurityDescriptor(&sd,SE CURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd,true, NULL,false);
sa.lpSecurityDescriptor = &sd;
}
else
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true;
// Создаем трубу STDIN
if (!CreatePipe(&newstdin,&write_stdin ,&sa,0))
throw Exception("Cannot create STDIN");
// Создаем трубу STDOUT
if (!CreatePipe(&read_stdout,&newstdou t,&sa,0))
{
CloseHandle(newstdin);
CloseHandle(write_stdin);
throw Exception("Cannot create STDOUT");
}
GetStartupInfo(&si);
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOW WINDOW;
si.wShowWindow = SW_SHOWNORMAL;
si.hStdOutput = newstdout;
si.hStdInput = newstdin;
si.hStdError = newstdout;
//создаем дочерний процесс
if (!CreateProcess(NULL,app_spawn.c_st r(),&sa,NULL,TRUE,CREATE_NEW_CONSOL E,NULL,NULL,&si,&pi))
{
CloseHandle(newstdin);
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
throw Exception("Cannot create process:\n"+String(app_spawn));
}
else
{
Params *param = new Params; //не забыть освободить память
param->hProcess = pi.hProcess;
param->hWnd = frmMain->Handle; //хэндл того окна, которому надо послать сообщение
TerminateHandle = CreateThread(NULL,0,(DWORD (WINAPI*)(void*))ThreadProc,param,0 ,NULL);
}
pExit = 0;
bzero(buf);
Started = true;
frmMain->Timer->Enabled = true;
}
catch (Exception &E)
{
Started = false;
MessageBox(0,E.Message.c_str(),0,MB _ICONERROR);
}
}
|
Цитата:
String ReadPipe()
{
try
{
if(!Started)
throw Exception("Server is not started");
String Line;
GetExitCodeProcess(pi.hProcess, &pExit);
if (pExit != STILL_ACTIVE)
throw Exception("Server is already stopped");
PeekNamedPipe(read_stdout, buf, 1023, &bread, &avail, NULL);
//Проверяем, есть ли данные для чтения в stdout
if (bread != 0)
{
bzero(buf);
if (avail > 1023)
{
while (bread >= 1023)
{
ReadFile(read_stdout,buf,1023,&brea d,NULL);
OemToAnsi(buf, buf);
Line = buf;
bzero(buf);
}
}
else
{
ReadFile(read_stdout,buf,1023,&brea d,NULL);
OemToAnsi(buf, buf);
Line = buf;
}
// Это так выравниваем конец строки и возврат коретки (для разных приложений)
Line = StringReplace(Line, "\r\n", "\n", TReplaceFlags() <<rfReplaceAll);
Line = StringReplace(Line, "\n", "\r\n", TReplaceFlags() <<rfReplaceAll);
return Line;
}
}
catch(Exception &E)
{
StopPipe();
frmMain->Timer->Enabled = false;
MessageBox(0,("Read: "+E.Message).c_str(),0,MB_ICONWARNI NG);
}
return "";
}
|
Вызовы:
Цитата:
StartPipe("\"d:\\test.exe\"");
Timer->Enabled = true;
//В таймере:
String str = ReadPipe();
if (str != "")
mempipe->Lines->Add(str);
|
В качестве консольной программы выступает моя тестовая программа с таким кодом:
Цитата:
for (int i = 0; i < 100000; i++)
{
cout <<i <<" ";
Sleep(2);
}
|
MASM Builder - Бесплатная IDE для MASM32 от русских разработчиков.
|