Создание дочерних процессов из основного приложения с помощью CreateProcess - PullRequest
0 голосов
/ 29 апреля 2020

Я хочу запустить B.exe в моем основном приложении A.exe как ребенок. Я знаю, как сделать это в C#, но я не могу найти ничего на Inte rnet, чтобы показать мне, как это сделать в C ++.

Я хочу запустить EXE в моем основной процесс, и когда мой основной процесс отключается, дочерние процессы тоже закрываются.

Как и Unity, например:

Unity EXE

Я знаю, что могу использовать WinExec() для создания дочерних процессов, но мне нужно сделать это с помощью CreateProcess().

Консольное приложение CHILD cpp:

#include "pch.h"
#include <iostream>
#include <Windows.h>

using namespace std;

int main()
{
    cout << "Child App is running..." << endl;
    while (true)
    {

    }
}

Консольное приложение MainApp cpp:

#include "pch.h"
#include <iostream>
#include <Windows.h>

using namespace std;

#define CHILD_PROCESS L"ChildApp.exe"
#define _WIN32_WINNT 0x05010000

#include <windows.h>
#include <winbase.h>

HANDLE Jobject = CreateJobObject(NULL,L"Job");

JOBOBJECT_EXTENDED_LIMIT_INFORMATION JBLI;

int CreateChildProcess(const wchar_t* chile_pe) {

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));

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

    try
    {
        if (Jobject == NULL)
        {throw "COULD NOT CREATE JOB OBJECT!";}

        if (!AssignProcessToJobObject(Jobject, OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId())))
        { return 1; }

        if (!QueryInformationJobObject(Jobject, JobObjectExtendedLimitInformation, &JBLI, sizeof(JBLI), NULL))
        { return 2; }

        JBLI.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_BREAKAWAY_OK;
        if (!SetInformationJobObject(Jobject, JobObjectExtendedLimitInformation, &JBLI, sizeof(JBLI)))
        { return 3; }

        CreateProcess((LPWSTR)chile_pe, NULL, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);

        std::cout << "Child Process ID: " << pi.dwProcessId << "\tThread ID: " << pi.dwThreadId << "\tHandle: " << pi.hProcess << "\n";

        WaitForSingleObject(pi.hProcess, INFINITE);

        TerminateProcess(pi.hProcess, 1816);

        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        CloseHandle(Jobject);

        return -1;
    }
    catch (char* Message)
    {
        std::cout << Message << " " << GetLastError() << "\n";
        return 0;
    }    
}

int main()
{
    cout << "MainApp Started..." << endl;

    cout << "Starting Child Process..." << endl;

    int childproc = CreateChildProcess(CHILD_PROCESS);

    if (childproc == -1) {
        cout << "MainApp Finished." << endl;
    }
    else {
        cout << "MainApp Finished with Error : " << childproc << endl;
    }

    getchar();
}

Ответы [ 3 ]

0 голосов
/ 29 апреля 2020

Как комментарии @Remy, вы используете JOB_OBJECT_LIMIT_BREAKAWAY_OK + CREATE_BREAKAWAY_FROM_JOB для создания дочернего процесса, который не связан с заданием.

Попробуйте вместо этого использовать JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE и CREATE_NO_WINDOW, создать неконсольный дочерний процесс. Затем вы можете завершить работу в диспетчере задач, если дочерний процесс завершится, дочерний процесс завершится.

#define _WIN32_WINNT 0x05010000
#include <Windows.h>
#include <iostream>
#include <winbase.h>
#define CHILD_PROCESS L"C:\\Users\\drakew\\source\\repos\\child\\Debug\\Child.exe"

using namespace std;

int CreateChildProcess(const wchar_t* chile_pe) 
{
    HANDLE Jobject;
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION JBLI;
    PROCESS_INFORMATION pi,pi1,pi2;
    ZeroMemory(&pi, sizeof(pi));
    STARTUPINFO si,si1,si2;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    try
    {
        Jobject = CreateJobObjectW(NULL, L"Job");
        if (Jobject == NULL)
        {
            throw "COULD NOT CREATE JOB OBJECT!";
        }

        if (!AssignProcessToJobObject(Jobject, OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId())))
        {
            return 1;
        }

        if (!QueryInformationJobObject(Jobject, JobObjectExtendedLimitInformation, &JBLI, sizeof(JBLI), NULL))
        {
            return 2;
        }

        JBLI.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
        if (!SetInformationJobObject(Jobject, JobObjectExtendedLimitInformation, &JBLI, sizeof(JBLI)))
        {
            return 3;
        }

        if (!CreateProcessW(chile_pe, NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
        {
            cout << "CreateProcess failed with " << GetLastError() << endl;
            return 4;
        }

        cout << "Child Process ID: " << pi.dwProcessId << "\tThread ID: " << pi.dwThreadId << "\tHandle: " << pi.hProcess << endl;

        WaitForSingleObject(pi.hProcess, INFINITE);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);

        //TerminateProcess(pi.hProcess, 1816);

        CloseHandle(Jobject);
        return -1;
    }
    catch (char* Message)
    {
        cout << Message << " " << GetLastError() << endl;
        return 0;
    }
}

int main()
{
    cout << "MainApp Started..." << endl;
    cout << "Starting Child Process..." << endl;

    int childproc = CreateChildProcess(CHILD_PROCESS);

    if (childproc == -1) {
        cout << "MainApp Finished." << endl;
    }
    else {
        cout << "MainApp Finished with Error : " << childproc << endl;
    }

    getchar();
}

результат:

image

0 голосов
/ 29 апреля 2020

Вот решение для создания любого приложения в детстве, благодаря себе;)

Полный пример:

#include <iostream>
#include <Windows.h>
#include <utility>

using namespace std;

#define CHILD_PROCESS L"ChildAppWin.exe"

#include <windows.h>
#include <winbase.h>


HWND child_hwnd = 0x0;
int timeout_time = 10000;
int timeout_interval = 0;


BOOL CALLBACK EnumThreadWndProc(HWND hWnd, LPARAM lParam)
{

    if (hWnd != 0) {
        child_hwnd = hWnd;
    }

    return FALSE;   
}

HANDLE ghJob = CreateJobObject(NULL, NULL);  

void SetupJobSystem() {
    if (ghJob == NULL)
    {
        ::MessageBoxA(0, "Could not create job object", "TEST", MB_OK);
    }
    else
    {
        JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };

        jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
        if (0 == SetInformationJobObject(ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
        {
            ::MessageBoxA(0, "Could not SetInformationJobObject", "TEST", MB_OK);
        }
    }
}

int CreateChildProcess(const wchar_t* chile_pe) {

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));

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

    try
    {
        timeout_interval = 0;
        si.dwFlags = STARTF_USESHOWWINDOW;
        si.wShowWindow = SW_HIDE;

        BOOL create_child = CreateProcess((LPWSTR)chile_pe, NULL , NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
        if (!create_child) {
            cout << "Cant create child" << endl;
            return 6;
        }

        std::cout << "Child Process ID: " << pi.dwProcessId << "\tThread ID: " << pi.dwThreadId << "\tHandle: " << pi.hProcess << "\n";

        if (0 == AssignProcessToJobObject(ghJob, pi.hProcess))
        {
            ::MessageBox(0, L"Could not AssignProcessToObject", L"", MB_OK);
        }

        while (child_hwnd == 0x0) {
            EnumThreadWindows(pi.dwThreadId, EnumThreadWndProc, NULL);

            timeout_interval++;

            if(timeout_interval == timeout_time)
            {
                child_hwnd = (HWND)-215125;
            }
        }

        if (child_hwnd == (HWND)-215125) {
            cout << "Interprocess matching timeout." << endl;
            return 9;
        }

        if (child_hwnd != (HWND)-215125 || child_hwnd != 0x0) {
            std::cout << "Founded Window Handle : 0x" << child_hwnd << endl;
        }

        SetParent(child_hwnd, GetConsoleWindow());

        WaitForSingleObject(pi.hProcess, INFINITE);

        TerminateProcess(pi.hProcess, 1816);

        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);


        return -1;
    }
    catch (char* Message)
    {
        std::cout << Message << " " << GetLastError() << "\n";
        return 0;
    }

}

int main()
{
    cout << "MainApp Started..." << endl;

    cout << "Starting Child Process..." << endl;

    SetupJobSystem();

    int childproc = CreateChildProcess(CHILD_PROCESS);

    CloseHandle(ghJob);

    if (childproc == -1) {
        cout << "MainApp Finished." << endl;
    }
    else {

        cout << "MainApp Finished with Error : " << childproc << endl;
    }

    getchar();
}
0 голосов
/ 29 апреля 2020

Используйте CreateProcess для создания дочернего процесса. В качестве третьего параметра передайте ему HANDLE. С помощью этого HANDLE вы можете изящно остановить дочерний процесс, когда ваш основной процесс вот-вот закроется.

Чтобы остановить дочерний процесс, передайте функцию HANDLE в TerminateProcess в качестве Первый параметр.

Не забудьте CloseHandle после того, как вы уничтожили ребенка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...