To spawn an external process and capture its execution, usually pipes are used. In Visual C++ you can choose between two options: the first (one and simplest) is to exploit the _popen function, the second one is to use the CreatePipe function. In the following I describe the source codes of both methos. Moreover remember that the _popen function does not work in Win32 application that are executed without consolle (so linked with the /SUBSYSTEM:WINDOWS flag).
The _popen way:
#define BUFSIZE 1024
FILE *f = NULL;
char buffer[BUFSIZE] = "";
chdir("c:/WorkingDirectory");
int exitcode = 0;
if (!(f = _popen("\"process.exe\"", "r"))) {
printf("popen error\n");
return;
}
while(!feof(f)) {
if (fgets(buffer, BUFSIZE, f) != NULL)
printf(buffer);
}
exitcode = _pclose(f);
The CreatePipe way:
#define BUFSIZE 1024
char buf[BUFSIZE]; //i/o buffer
STARTUPINFO si;
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd; //security information for pipes
PROCESS_INFORMATION pi;
HANDLE newstdin,newstdout,read_stdout,write_stdin; //pipe handles
InitializeSecurityDescriptor(&sd,SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, true, NULL, false);
sa.lpSecurityDescriptor = &sd;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = true; //allow inheritable handles
if (!CreatePipe(&newstdin,&write_stdin,&sa,0)) //create stdin pipe
{
printf("Error CreatePipe\n");
return;
}
if (!CreatePipe(&read_stdout,&newstdout,&sa,0)) //create stdout pipe
{
printf("Error CreatePipe\n");
CloseHandle(newstdin);
CloseHandle(write_stdin);
return;
}
GetStartupInfo(&si); //set startupinfo for the spawned process
/*
The dwFlags member tells CreateProcess how to make the process.
STARTF_USESTDHANDLES validates the hStd* members. STARTF_USESHOWWINDOW
validates the wShowWindow member.
*/
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdOutput = newstdout;
si.hStdError = newstdout; //set the new handles for the child process
si.hStdInput = newstdin;
char app_spawn[] = "process.exe"; //sample, modify for your
//system
//spawn the child process
if (!CreateProcess(app_spawn,NULL,NULL,NULL,TRUE,CREATE_NEW_CONSOLE,
NULL,"c:/WorkingDirectory",&si,&pi))
{
this->log("Error CreateProcess\n");
CloseHandle(newstdin);
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
return;
}
unsigned long exit=0; //process exit code
unsigned long bread; //bytes read
unsigned long avail; //bytes available
ZeroMemory(buf, sizeof(buf));
for(;;) //main program loop
{
GetExitCodeProcess(pi.hProcess,&exit); //while the process is running
if (exit != STILL_ACTIVE)
break;
PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
//check to see if there is any data to read from stdout
if (bread != 0)
{
ZeroMemory(buf, sizeof(buf));
if (avail > BUFSIZE-1)
{
while (bread >= BUFSIZE-1)
{
ReadFile(read_stdout,buf,BUFSIZE-1,&bread,NULL); //read the stdout pipe
printf(buf);
ZeroMemory(buf, sizeof(buf));
}
}
else {
printf(read_stdout,buf,BUFSIZE-1,&bread,NULL);
this->log(buf);
}
}
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(newstdin); //clean stuff up
CloseHandle(newstdout);
CloseHandle(read_stdout);
CloseHandle(write_stdin);
No comments:
Post a Comment