/////////////////////////////////////////////////////////////////////// // spawnProc.cpp - Demonstrate Creation of a Child Process // // // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2012 // /////////////////////////////////////////////////////////////////////// /* * This demonstration: * - Creates an anonymous pipe to communicate with a child process * - Creates a child process and specifies that it inherit the * pipe read and write handles * - Reads the pipe to get child output * - closes the pipe */ #include #include using namespace std; //----< retrieve system error message >-------------------------------- std::string GetLastErrorString() { DWORD errorCode = GetLastError(); DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER; LPCVOID lpSource = NULL; DWORD dwMessageID = errorCode; DWORD dwLanguageId = MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US); LPSTR lpBuffer; DWORD nSize = 0; va_list *Arguments = NULL; FormatMessage( dwFlags,lpSource,dwMessageID,dwLanguageId, (LPTSTR)&lpBuffer,nSize,Arguments ); if(lpBuffer) return std::string(lpBuffer); return ""; } //----< Demonstrate Process Creation >--------------------------------- int main(int argc, char *argv[]) { cout << "\n Demonstrating CreateProcess - may help with Project #3 " << "\n========================================================\n"; if(argc < 2) { cout << "\n please enter the name of a program to execute, including .exe"; return 1; } // declare structures for CreateProcess STARTUPINFO startInfo; // we fill to control startup PROCESS_INFORMATION procInfo; // CreateProcess will fill // set parameters for CreatePipe SECURITY_ATTRIBUTES sa; sa.bInheritHandle = TRUE; // tells pipe to support inheritance of handles sa.lpSecurityDescriptor = NULL; // client process security properties sa.nLength = sizeof(sa); HANDLE hRead; HANDLE hWrite; if(!::CreatePipe(&hRead, &hWrite, &sa, 0)) { std::cout << "\n could not create anonymous pipe\n\n"; std::cout << "\n\n" << GetLastErrorString().c_str() << "\n\n"; return 1; } // save parent stdout handle HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); // Set parent stdout handle to pipe write handle. // This lets child access pipe. SetStdHandle(STD_OUTPUT_HANDLE,hWrite); char *pCL; if(argc < 3) /* was 3 */ pCL = "default argument"; else pCL = argv[2]; // expects quoted string with arguments separated by spaces LPCTSTR appName = argv[1]; // program to run LPTSTR commandLine = pCL; // main's args LPSECURITY_ATTRIBUTES procSec = &sa; // default security LPSECURITY_ATTRIBUTES thrdSec = NULL; // default security BOOL inheritHandles = TRUE; // inherit so child can get pipe Write Handle DWORD createFlags = CREATE_NEW_CONSOLE; // make a console //DWORD createFlags = CREATE_NO_WINDOW; // don't allocate a console for child LPVOID environment = NULL; // caller's evironment LPCTSTR currentPath = NULL; // default dir LPSTARTUPINFO pStartInfo = &startInfo; // set process style LPPROCESS_INFORMATION pPrInfo = &procInfo; // retrieve info string buildTitle = "Child Process: "; buildTitle += argv[1]; GetStartupInfo(&startInfo); startInfo.lpTitle = (char*)buildTitle.c_str(); startInfo.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE | STARTF_USESTDHANDLES; startInfo.dwX = 200; startInfo.dwY = 250; startInfo.dwXSize = 500; startInfo.dwYSize = 300; startInfo.hStdOutput = hWrite; startInfo.hStdError = hWrite; cout << "\n Attempting to start: " << argv[1] << "\n with arguments: " << pCL << endl; // experiment //appName = "c:/windows/system32/notepad.exe"; //commandLine = "C:/su/CSE687/code/asserts/asserts.cpp"; // end experiment BOOL OK = CreateProcess( appName,commandLine,procSec,thrdSec,inheritHandles, createFlags,environment,currentPath,pStartInfo,pPrInfo ); CloseHandle(hWrite); // restore parent stdout handle SetStdHandle((DWORD)STD_OUTPUT_HANDLE,hStdout); if(!OK) { cout << "\n failed to create process: " << appName << "\n\n"; cout << GetLastErrorString().c_str() << "\n\n"; } // read child's output from pipe const size_t BUFSIZE = 256; char buffer[BUFSIZE+1]; DWORD dwRead; for(;;) { cout << "\n reading pipe:\n"; if(!ReadFile(hRead,buffer,BUFSIZE,&dwRead,NULL)) break; buffer[dwRead] = 0; std::string str(buffer); cout << str.c_str(); if(str.find("quit") < str.size()) break; } // if you want to see the child window you need to // wait until the user closes it, then quit WaitForSingleObject(procInfo.hProcess,INFINITE); CloseHandle(hRead); cout << "\n\n"; return 0; }