다른 프로세스 실행하기 (Launching Other Processes)
Win32 프로세스는 쓰레드를 실행하는 것과 같이 쉽게 다른 프로세스를 실행시킬 수 있다. 아래 문장은 C 드라이브의 Windows 디렉토리에 있는 Notepad.exe 를 실행한다.
STARTUPINFO si; ::ZeroMemory (&si, sizeof (STARTUPINFO)); si.cb = sizeof (STARTUPINFO); PROCESS_INFORMATION pi; if (::CreateProcess (NULL, _T ("C:\\Windows\\Notepad"), NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { ::CloseHandle (pi.hThread); ::CloseHandle (pi.hProcess); } |
::CreateProcess 는 (선택적으로 경로) 실행가능한 파일의 이름을 받아 그것을 로드하고 실행하는 다재다능한 함수이다. 만약 드라이브 명과 디렉토리 명이 실행가능한 파일 이름에서 빠졌다면, 시스템은 자동적으로 Windows 디렉토리, Windows system 디렉토리, 현재 Path 에 있는 모든 디렉토리, 그리고 선택된 다른 위치에서 그 파일을 찾는다. 파일 이름은 또한 명령어 파라미터를 포함할 수 있다.
"C:\\Windows\\Notepad C:\\Windows\\Desktop\\Ideas.txt"
::CreateProcess 는 프로세스 핸들(hProcess)과 프로세스의 주 쓰레드 핸들(hThred)을 포함하는 프로세스에 관한 정보를 가지는 PROCESS_INFORMATION 구조체를 채운다. 프로세스가 시작된 후에는 ::CloseHandle 을 이용하여 이 핸들들을 받드시 닫아야 한다. 핸들을 더 이상 사용하지 않는다면, ::CreateProcess 가 반환하는 순간 그것들을 닫을 수 있다.
::CreateProcess 로부터 0이 아닌 값이 반환되면 프로세스는 성공적으로 실행되었다는 것을 의미한다. Win32 프로세스는 비동기적으로 시작되고 실행된다, 그래서 ::CreateProcess 는 프로세스가 종료될 때까지 기다리지 않는다. 만일 다른 프로세스를 시작하고 그것이 종료될 때까지 현재 프로세스를 중지시키고 싶다면, 그 프로세스 핸들에 대해 ::WaitForSingleObject 를 호출하라.
STARTUPINFO si; ::ZeroMemory (&si, sizeof (STARTUPINFO)); si.cb = sizeof (STARTUPINFO); PROCESS_INFORMATION pi; if (::CreateProcess (NULL, _T ("C:\\Windows\\Notepad"), NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { ::CloseHandle (pi.hThread); ::WaitForSingleObject (pi.hProcess, INFINITE); ::CloseHandle (pi.hProcess); } |
프로세스는 쓰레드처럼 종료 코드를 가진다. 만일 ::WaitForSingleObject 가 WAIT_FAILED 가 아닌 다른 값을 반환한다면, 그 프로세스의 종료 코드를 얻기 위해 ::GetExitCodeProcess 를 호출할 수 있다.
가끔 프로세스가 시작된 후 사용자 입력에 반응하기까지 충분한 시간을 기다릴 필요가 있다. 예륻 들어, 프로세스 A가 프로세스 B를 실행시키고 프로세스 B는 윈도우를 생성한다 그리고 프로세스 A는 그 윈도우에게 메시지를 보내길 원한다, 프로세스 A는 프로세스 B에게 윈도우를 생성하고 메시지 처리를 시작하기 위한 시간을 주기위해 ::CreateProcess 가 반환된 후 잠시동안 기다려야 할 것이다. 이 문제는 Win32 ::WaitForInputIdle 함수를 이용하면 쉽게 해결된다.
STARTUPINFO si; ::ZeroMemory (&si, sizeof (STARTUPINFO)); si.cb = sizeof (STARTUPINFO); PROCESS_INFORMATION pi; if (::CreateProcess (NULL, _T ("C:\\Windows\\Notepad"), NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { ::CloseHandle (pi.hThread); ::WaitForInputIdle (pi.hProcess, INFINITE); // Get B's window handle and send or post a message. ::CloseHandle (pi.hProcess); } |
::WaitForInputIdle 은 지정한 프로세스가 메시지 처리를 시작하고 메시지 큐가 비어 있게 될 때까지 대기한다. 윈도우 핸들을 찾기 위한 코드를 보여주지 않았다 왜냐하면 프로세스 핸들을 윈도우 핸들로 변환하기 위한 간단한 MFC 또는 API 함수가 없기 때문이다. 대신, 소유하고 있는 프로세스의 어떤 알려진 속성을 근거로 그 윈도우를 찾는 ::EnumWindows, ::FindWindow, 또는 관련 함수를 사용해야만 한다.
참고 : Programming with MFC 2nd Edition