Windows 실행 파일을 실행하기 위해 C++에서 ::CreateProcess를 어떻게 호출합니까?

StackOverflow https://stackoverflow.com/questions/42531

  •  09-06-2019
  •  | 
  •  

문제

다음과 같은 예를 찾고 있습니다.

  1. EXE를 실행합니다
  2. EXE가 완료될 때까지 기다립니다.
  3. 실행 파일이 완료되면 모든 핸들을 올바르게 닫습니다.
도움이 되었습니까?

해결책

이 같은:

STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;
if (CreateProcess(path, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
    WaitForSingleObject(processInfo.hProcess, INFINITE);
    CloseHandle(processInfo.hProcess);
    CloseHandle(processInfo.hThread);
}

다른 팁

에 예가 있습니다. http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx

그냥 교체하세요 argv[1] 프로그램이 포함된 상수 또는 변수를 사용하세요.

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void _tmain( int argc, TCHAR *argv[] )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    if( argc != 2 )
    {
        printf("Usage: %s [cmdline]\n", argv[0]);
        return;
    }

    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
        argv[1],        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        printf( "CreateProcess failed (%d).\n", GetLastError() );
        return;
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
}

응용 프로그램이 Windows GUI 응용 프로그램인 경우 아래 코드를 사용하여 대기하는 것은 응용 프로그램에 대한 메시지가 처리되지 않으므로 이상적이지 않습니다.사용자에게는 애플리케이션이 중단된 것처럼 보입니다.

WaitForSingleObject(&processInfo.hProcess, INFINITE)

다음과 같은 것 테스트되지 않은 아래 코드는 Windows 메시지 대기열을 계속 처리하고 애플리케이션이 계속 응답하므로 더 나을 수 있습니다.

//-- wait for the process to finish
while (true)
{
  //-- see if the task has terminated
  DWORD dwExitCode = WaitForSingleObject(ProcessInfo.hProcess, 0);

  if (   (dwExitCode == WAIT_FAILED   )
      || (dwExitCode == WAIT_OBJECT_0 )
      || (dwExitCode == WAIT_ABANDONED) )
  {
    DWORD dwExitCode;

    //-- get the process exit code
    GetExitCodeProcess(ProcessInfo.hProcess, &dwExitCode);

    //-- the task has ended so close the handle
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ProcessInfo.hProcess);

    //-- save the exit code
    lExitCode = dwExitCode;

    return;
  }
  else
  {
    //-- see if there are any message that need to be processed
    while (PeekMessage(&message.msg, 0, 0, 0, PM_NOREMOVE))
    {
      if (message.msg.message == WM_QUIT)
      {
        return;
      }

      //-- process the message queue
      if (GetMessage(&message.msg, 0, 0, 0))
      {
        //-- process the message
        TranslateMessage(&pMessage->msg);
        DispatchMessage(&pMessage->msg);
      }
    }
  }
}

exe가 콘솔 앱인 경우 stdout 및 stderr을 읽는 데 관심이 있을 수 있습니다. 이에 대해 겸허하게 다음 예를 참조하겠습니다.

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q190351

약간의 코드이지만 생성하고 읽기 위해 이 코드의 변형을 사용했습니다.

준 관련 참고 사항에서 현재 프로세스보다 더 많은 권한이 있는 프로세스를 시작하려는 경우(예: 일반 사용자로 실행되는 기본 앱에서 관리자 권한이 필요한 관리 앱 실행) 다음을 수행할 수 없습니다. UAC 대화 상자가 실행되지 않으므로 Vista에서는 CreateProcess()를 사용하여 수행하십시오(활성화되어 있다고 가정).그러나 ShellExecute()를 사용하면 UAC 대화 상자가 트리거됩니다.

사용한다는 점을 명심하세요. WaitForSingleObject 이 시나리오에서는 문제가 발생할 수 있습니다.다음은 내 웹사이트의 팁에서 발췌한 것입니다.

애플리케이션에 창이 있지만 메시지를 펌핑하지 않기 때문에 문제가 발생합니다.생성된 애플리케이션이 브로드캐스트 대상 중 하나를 사용하여 SendMessage를 호출하는 경우(HWND_BROADCAST 또는 HWND_TOPMOST), SendMessage는 모든 애플리케이션이 메시지를 처리할 때까지 새 애플리케이션으로 반환되지 않습니다. 그러나 앱은 메시지를 펌핑하지 않기 때문에 메시지를 처리할 수 없습니다....그래서 새로운 앱이 작동을 멈추게 되고, 여러분의 기다림은 절대 성공하지 못할 것입니다....이중 자물쇠.

생성된 애플리케이션을 절대적으로 제어할 수 있는 경우 SendMessage 대신 SendMessageTimeout을 사용하는 등 취할 수 있는 조치가 있습니다(예:DDE 시작의 경우(아직 누군가 이를 사용하고 있는 경우)그러나 예를 들어 SetSysColors API를 사용하는 것과 같이 제어할 수 없는 암시적 SendMessage 브로드캐스트를 유발하는 상황이 있습니다.

이 문제를 해결하는 유일한 안전한 방법은 다음과 같습니다.

  1. Wait를 별도의 스레드로 분할하거나
  2. Wait에서 시간 제한을 사용하고 Wait 루프에서 PeekMessage를 사용하여 메시지를 펌핑하는지 확인하거나
  3. 사용 MsgWaitForMultipleObjects API.

다음은 Windows 10에서 작동하는 새로운 예입니다.windows10 SDK를 사용하는 경우 CreateProcessW를 대신 사용해야 합니다.이 예는 주석 처리되어 있으며 설명이 필요하지 않습니다.

#ifdef _WIN32
#include <Windows.h>
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#include <cstdlib>
#include <string>
#include <algorithm>

class process
{
public:

    static PROCESS_INFORMATION launchProcess(std::string app, std::string arg)
    {

        // Prepare handles.
        STARTUPINFO si;
        PROCESS_INFORMATION pi; // The function returns this
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );

        //Prepare CreateProcess args
        std::wstring app_w(app.length(), L' '); // Make room for characters
        std::copy(app.begin(), app.end(), app_w.begin()); // Copy string to wstring.

        std::wstring arg_w(arg.length(), L' '); // Make room for characters
        std::copy(arg.begin(), arg.end(), arg_w.begin()); // Copy string to wstring.

        std::wstring input = app_w + L" " + arg_w;
        wchar_t* arg_concat = const_cast<wchar_t*>( input.c_str() );
        const wchar_t* app_const = app_w.c_str();

        // Start the child process.
        if( !CreateProcessW(
            app_const,      // app path
            arg_concat,     // Command line (needs to include app path as first argument. args seperated by whitepace)
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            0,              // No creation flags
            NULL,           // Use parent's environment block
            NULL,           // Use parent's starting directory
            &si,            // Pointer to STARTUPINFO structure
            &pi )           // Pointer to PROCESS_INFORMATION structure
        )
        {
            printf( "CreateProcess failed (%d).\n", GetLastError() );
            throw std::exception("Could not create child process");
        }
        else
        {
            std::cout << "[          ] Successfully launched child process" << std::endl;
        }

        // Return process handle
        return pi;
    }

    static bool checkIfProcessIsActive(PROCESS_INFORMATION pi)
    {
        // Check if handle is closed
            if ( pi.hProcess == NULL )
            {
                printf( "Process handle is closed or invalid (%d).\n", GetLastError());
                return FALSE;
            }

        // If handle open, check if process is active
        DWORD lpExitCode = 0;
        if( GetExitCodeProcess(pi.hProcess, &lpExitCode) == 0)
        {
            printf( "Cannot return exit code (%d).\n", GetLastError() );
            throw std::exception("Cannot return exit code");
        }
        else
        {
            if (lpExitCode == STILL_ACTIVE)
            {
                return TRUE;
            }
            else
            {
                return FALSE;
            }
        }
    }

    static bool stopProcess( PROCESS_INFORMATION &pi)
    {
        // Check if handle is invalid or has allready been closed
            if ( pi.hProcess == NULL )
            {
                printf( "Process handle invalid. Possibly allready been closed (%d).\n");
                return 0;
            }

        // Terminate Process
            if( !TerminateProcess(pi.hProcess,1))
            {
                printf( "ExitProcess failed (%d).\n", GetLastError() );
                return 0;
            }

        // Wait until child process exits.
            if( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_FAILED)
            {
                printf( "Wait for exit process failed(%d).\n", GetLastError() );
                return 0;
            }

        // Close process and thread handles.
            if( !CloseHandle( pi.hProcess ))
            {
                printf( "Cannot close process handle(%d).\n", GetLastError() );
                return 0;
            }
            else
            {
                pi.hProcess = NULL;
            }

            if( !CloseHandle( pi.hThread ))
            {
                printf( "Cannot close thread handle (%d).\n", GetLastError() );
                return 0;
            }
            else
            {
                 pi.hProcess = NULL;
            }
            return 1;
    }
};//class process
#endif //win32
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top