Come faccio a chiamare ::CreateProcess in c++ per lanciare un eseguibile di Windows?

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

  •  09-06-2019
  •  | 
  •  

Domanda

Cercando un esempio che:

  1. Lancia un EXE
  2. Attende che l'EXE alla fine.
  3. Correttamente la chiusura di tutte le maniglie quando il file eseguibile.
È stato utile?

Soluzione

Qualcosa di simile a questo:

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);
}

Altri suggerimenti

C'è un esempio http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx

Basta sostituire il argv[1] con il vostro costante o variabile contenente il programma.

#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 );
}

Se si è un'applicazione di Windows GUI dell'applicazione, quindi, utilizzando il codice riportato di seguito per effettuare l'attesa non è l'ideale, come i messaggi per la vostra applicazione non sarà sempre trattamento.Per l'utente non deve guardare come la vostra applicazione.

WaitForSingleObject(&processInfo.hProcess, INFINITE)

Qualcosa di simile non testata codice riportato di seguito potrebbe essere meglio come sarà mantenere l'elaborazione della coda di messaggi windows e l'applicazione risponde:

//-- 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);
      }
    }
  }
}

se il tuo exe succede ad essere un'applicazione console, si potrebbe essere interessati a leggere il stdout e stderr-per questo, io umilmente di fare riferimento a questo esempio:

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

E 'un po' di un boccone di codice, ma ho usato varianti di questo codice per deporre le uova e leggere.

Su un semi-nota correlata, se si desidera avviare un processo che ha più privilegi rispetto il tuo attuale processo (ad esempio, il lancio di un admin app che richiede i diritti di Amministratore, da tutti i principali app in esecuzione come utente normale), non è possibile farlo utilizzando CreateProcess() su Vista, dato che non attivano l'UAC di dialogo (se abilitato).Il controllo dell'account utente finestra di dialogo viene attivato quando si utilizza ShellExecute(), però.

Tenete presente che l'utilizzo WaitForSingleObject si può ottenere in difficoltà in questo scenario.Il seguente è stato tagliato da un suggerimento sul mio sito:

Il problema nasce dal fatto che l'applicazione dispone di una finestra, ma non è il pompaggio di messaggi.Se l'applicazione di generato richiama SendMessage con uno dei broadcast obiettivi (HWND_BROADCAST o HWND_TOPMOST), quindi la SendMessage non ritorno per la nuova applicazione fino a quando tutte le applicazioni hanno gestito il messaggio - ma la tua app non è in grado di gestire il messaggio perché non è il pompaggio di messaggi....così la nuova app si blocca, in modo che la vostra attesa non riesce mai....Una situazione di STALLO.

Se si dispone di un controllo assoluto l'applicazione di generato, poi ci sono misure si possono adottare, come l'utilizzo di SendMessageTimeout piuttosto che SendMessage (ad es.per DDE iniziazioni, se qualcuno è ancora usando).Ma ci sono situazioni che, a causa implicita SendMessage trasmissioni quali non si ha alcun controllo, ad esempio utilizzando le API di SetSysColors per esempio.

L'unica modi sicuri questo turno sono:

  1. dividere l'Attesa in un thread separato, o
  2. utilizzare un timeout durante l'Attesa e l'uso PeekMessage in Attesa del ciclo per garantire che la pompa di messaggi, o
  3. utilizzare il MsgWaitForMultipleObjects API.

Ecco un nuovo esempio che funziona su windows 10.Quando si utilizza il windows10 sdk è necessario utilizzare CreateProcessW invece.Questo esempio è un commento e speriamo di auto esplicativo.

#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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top