Как правильнее следить за child процессом
От: C0x  
Дата: 17.10.18 15:59
Оценка:
Есть Лаунчер. Он стартует некое приложение и скрывается из виду. Нужно как только дочерний процесс завершиться показать лаунчер снова.

Пока делаю так в Лаунчере:

0. ::ShowWindow(parentHwnd, SW_HIDE);
1. RunProcess(path, args);
2.

RepeatOnTimeout([parentHwnd]()->bool {
                //работает в отдельном потоке

                if (CheckProcessExists(L"child.exe"))
                {

                    return true;
                }
                //if ended
                ::ShowWindow(parentHwnd, SW_SHOW);
                return false;
            }, 1000);


Как можно это сделать более правильно?

RunProcess такой:


void RunProcess(const wstring &path, const wstring &args)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    HANDLE g_hChildStd_OUT_Rd = NULL;
    HANDLE g_hChildStd_OUT_Wr = NULL;

    SECURITY_ATTRIBUTES saAttr;

    ZeroMemory(&saAttr, sizeof(SECURITY_ATTRIBUTES));
    memset(&saAttr, 0, sizeof(SECURITY_ATTRIBUTES));
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    //saAttr.bInheritHandle = TRUE;
    //saAttr.lpSecurityDescriptor = NULL;



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

    //si.hStdError = g_hChildStd_OUT_Wr;
    //si.hStdOutput = g_hChildStd_OUT_Wr;
    //si.dwFlags |= STARTF_USESTDHANDLES;


    
    wstring cmdLine = WStrF(L"\"%s\" %s", path.c_str(), args.c_str());
    WCHAR buff[4096];
    wcscpy(buff, cmdLine.c_str());

    BOOL ret = CreateProcess(NULL, buff,
        NULL,
        NULL,
        TRUE,
        NULL,
        NULL,
        NULL,
        &si,
        &pi); 

    if (!ret)
    {
        throw exception("Failed to run process");
    }
}
Re: Как правильнее следить за child процессом
От: C0x  
Дата: 17.10.18 16:22
Оценка:
Сделал вариант с запуском child в отдельном потоке и ожидании его закрытия через

std::thread([](){
// ...
RunProcessAndGetOutput(const wstring &path, const wstring &args, wstring &out)
// ...
}).detach();


Так вроде бы корректнее.
Re: Как правильнее следить за child процессом
От: Stanislav V. Zudin Россия  
Дата: 17.10.18 16:32
Оценка:
Здравствуйте, C0x, Вы писали:

C0x>Есть Лаунчер. Он стартует некое приложение и скрывается из виду. Нужно как только дочерний процесс завершиться показать лаунчер снова.

...
C0x>Как можно это сделать более правильно?

Я бы сделал WaitForSingleObject( pi.hProcess, INFINITE );

А если хочется еще и ловить закрытие лаунчера, то создать евент и засунуть оба хендла в WaitForMultipleObjects, но потребуется второй поток, чтобы обрабатывать события от GUI лаунчера.
А можно не создавать евент, а выходить из WaitForSingleObject по таймауту и смотреть, не изменилось ли что-то в состоянии лаунчера.
_____________________
С уважением,
Stanislav V. Zudin
Re: Как правильнее следить за child процессом
От: Pavel Dvorkin Россия  
Дата: 17.10.18 16:34
Оценка:
Здравствуйте, C0x, Вы писали:

C0x>Есть Лаунчер. Он стартует некое приложение и скрывается из виду. Нужно как только дочерний процесс завершиться показать лаунчер снова.



C0x> BOOL ret = CreateProcess(NULL, buff,

C0x> NULL,
C0x> NULL,
C0x> TRUE,
C0x> NULL,
C0x> NULL,
C0x> NULL,
C0x> &si,
C0x> &pi);

WaitForSingleObject(pi.hProcess, INFINITE);

Если лаунчеру делать во время ожидания нечего, то и поток не нужен.
With best regards
Pavel Dvorkin
Re[2]: Как правильнее следить за child процессом
От: ononim  
Дата: 18.10.18 06:51
Оценка: 10 (1)
SVZ>А если хочется еще и ловить закрытие лаунчера, то создать евент и засунуть оба хендла в WaitForMultipleObjects, но потребуется второй поток, чтобы обрабатывать события от GUI лаунчера.
Для ожидания оконных событий и объектов ядра в одном потоке есть MsgWaitForMultipleObjects. Так что второго потока не нужно.
Как много веселых ребят, и все делают велосипед...
Re[2]: Как правильнее следить за child процессом
От: C0x  
Дата: 18.10.18 07:50
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>Здравствуйте, C0x, Вы писали:


C0x>>Есть Лаунчер. Он стартует некое приложение и скрывается из виду. Нужно как только дочерний процесс завершиться показать лаунчер снова.

SVZ>...
C0x>>Как можно это сделать более правильно?

SVZ>Я бы сделал WaitForSingleObject( pi.hProcess, INFINITE );


К сожалению вот эта строчка по неизведанным мне пока причинам блокирует отрисовку OpenGL графики в child процессе. То есть тупа открывается черное окно и висит и оба процесса чего-то ждут.

Сделал вот так и теперь все ок:

    BOOL ret = CreateProcess(NULL, buff,
            NULL,
            NULL,
            TRUE,
            CREATE_NO_WINDOW,
            NULL,
            NULL,
            &si,
            &pi);

        if (!ret)
        {
            break;
        }


        

        DWORD exitCode;
        ret = GetExitCodeProcess(pi.hProcess, &exitCode);

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

        if (!ret)
        {
            break;
        }

        CHAR chBuf[0x4000];
        memset(chBuf, '\0', sizeof(chBuf));

        DWORD dwRead = 0;
        BOOL bSuccess = FALSE;

        CloseHandle(g_hChildStd_OUT_Wr);
        g_hChildStd_OUT_Wr = NULL;
        for (;;)
        {

            bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, 0x4000, &dwRead, NULL);


            //if( ! bSuccess || dwRead == 0 ) break;
            if (bSuccess && dwRead > 0)
            {
                out += UTF8ToW(chBuf);
            }
            else
            {
                break;
            }
        }
        ok = true;

    } while (0);

    if (g_hChildStd_OUT_Rd != NULL)
        CloseHandle(g_hChildStd_OUT_Rd);
    if (g_hChildStd_OUT_Wr != NULL)
        CloseHandle(g_hChildStd_OUT_Wr);
Re[2]: Как правильнее следить за child процессом
От: C0x  
Дата: 18.10.18 07:52
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Если лаунчеру делать во время ожидания нечего, то и поток не нужен.


Нее, второй поток я специально сделал, т.к. работы хватает.
Re[3]: Как правильнее следить за child процессом
От: C0x  
Дата: 18.10.18 07:53
Оценка:
Здравствуйте, ononim, Вы писали:

SVZ>>А если хочется еще и ловить закрытие лаунчера, то создать евент и засунуть оба хендла в WaitForMultipleObjects, но потребуется второй поток, чтобы обрабатывать события от GUI лаунчера.

O>Для ожидания оконных событий и объектов ядра в одном потоке есть MsgWaitForMultipleObjects. Так что второго потока не нужно.

У меня основной поток это Sciter. Вся остальное работа идет в рабочих потоках по паттерну Command.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.