WINAPI CreateProcess дочерний процесс не запущен - PullRequest
0 голосов
/ 03 декабря 2018

Я использую статью в msdn о создании дочернего процесса , потому что это довольно близко к тому, чего я хочу достичь.

Вопросы в создании дочернего процесса c # , перенаправление с использованием конвейеров были полезны, я нашел несколько ошибок в моем подходе, но, скорее всего, больше ошибок, чем яудалось найти.

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

Из того, что я смог увидеть, дочерний процесс не выполняет код, который я создал для него, поэтому я могу создать дочерний процесс неправильно

Parent.cpp

      #include <windows.h> 
#include "pch.h"
#include <iostream>
#include <stdio.h>

HANDLE childInRead = NULL;
HANDLE childInWrite = NULL;
HANDLE childOutRead = NULL;
HANDLE childOutWrite = NULL;

HANDLE parentInRead = NULL;

#define BUFSIZE 4096

void CreateChildProcess() {
    TCHAR applicationName[] = TEXT("ChildTalk.exe");
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    BOOL success = FALSE;

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

    si.cb = sizeof(STARTUPINFO);
    si.hStdError = childInRead;
    si.hStdOutput = childInRead;
    si.hStdInput = childOutWrite;
    si.dwFlags |= STARTF_USESTDHANDLES;

    success = CreateProcess(NULL, applicationName, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);

    if (!success) {
        printf("Error creating child process \n");
    }
    else {
        printf("Child process successfuly created \n");
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
}

int main()
{
    printf("Parent process running.... \n");

    DWORD dRead, dWritten;
    CHAR chBuf[BUFSIZE];
    BOOL bSuccess = FALSE;

    SECURITY_ATTRIBUTES secAttr;
    secAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    secAttr.bInheritHandle = TRUE;
    secAttr.lpSecurityDescriptor = NULL;

    printf("Creating first pipe \n");

    if (!CreatePipe(&parentInRead, &childInWrite, &secAttr, 0)) {
        printf("\n error creating first pipe \n");
    }
    printf("Creating second pipe \n");

    if (!CreatePipe(&childOutWrite, &childOutRead, &secAttr, 0)) {
        printf("\n error creating second pipe \n");
    }

    if (!SetHandleInformation(parentInRead, HANDLE_FLAG_INHERIT, 0)) {
        printf("\n parentInRead SetHandleInformation \n");
    }
    if (!SetHandleInformation(childInWrite, HANDLE_FLAG_INHERIT, 0)) {
        printf("\n childInWrite SetHandleInformation \n");
    }

    childOutRead = GetStdHandle(STD_OUTPUT_HANDLE);
    parentInRead = GetStdHandle(STD_INPUT_HANDLE);

    printf("\n Creating child process..... \n");
    CreateChildProcess();

    for (;;){
        printf("Inside for loop \n");
        bSuccess = ReadFile(parentInRead, chBuf, BUFSIZE, &dRead, NULL);
        if (!bSuccess) {
            printf("error reading \n");
            break;
        }

        bSuccess = WriteFile(childInWrite, chBuf,
                    dRead, &dWritten, NULL);
        if (!bSuccess) {
            printf("error writing \n");
            break;
        }
    }
    return 0;
}

ChildTalk.cpp

 #include <windows.h>
#include <stdio.h>
#include "pch.h"

#define BUFSIZE 4096

int main()
{
    DWORD dRead, dWritten;
    CHAR chBuf[BUFSIZE];
    BOOL success = FALSE;
    HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);

    printf("Child process running....");

    if (stdIn == INVALID_HANDLE_VALUE || stdOut == INVALID_HANDLE_VALUE) {
        ExitProcess(1);
    }

    for (;;) {
        success = ReadFile(stdIn, chBuf, BUFSIZE, &dRead, NULL);
        if (!success || dRead == 0) break;

        success = WriteFile(stdOut, chBuf, dRead, &dWritten, NULL);
        if (!success) break;
    }
    return 0;
}

EDIT1: при выполнении кода ошибок нет, программа остается на

bSuccess = WriteFile(childStdOut, chBuf,
                        dRead, &dWritten, NULL);
            if (!bSuccess) {
                printf("error writing");
                break;
            } 

, потому что она ожидает ввода, но когда я что-то набираю, она печатаетсообщение об ошибке записи.Сообщение, которое я добавил в дочерний код «Дочерний процесс выполняется ....», не печатается

EDIT2: изменен код, потому что я думаю, что дескрипторы были неправильными, теперь он печатает «Внутри цикла», но все еще нет дочернего процесса,Нужно ли сначала запускать консольное приложение дочернего процесса?

1 Ответ

0 голосов
/ 07 декабря 2018

В вашем коде есть некоторые ошибки.

Во-первых,

childOutRead = GetStdHandle(STD_OUTPUT_HANDLE); parentInRead = GetStdHandle(STD_INPUT_HANDLE); дескриптор 2 получен из CreatePipe, сброшен в stdhandle и потерял дескриптор канала.

Во-вторых,

CreatePipe(&childOutWrite, &childOutRead, &secAttr, 0);

должно быть CreatePipe(&childOutRead, &childOutWrite, &secAttr, 0)

В-третьих,

дескриптор в SetHandleInformation () неверен.

Хорошо, давайте вернем ваш вопрос.

Для сокрытия дочернего процесса его дескриптор stdin / stdout помещается в дескриптор канала, поэтому вы не можете видеть консоль, но она работает в фоновом режиме.Я внес некоторые изменения в ваш пример (для простоты асинхронность не используется):

Parent.cpp

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

HANDLE childInRead = NULL;
HANDLE W1 = NULL;
HANDLE W2 = NULL;
HANDLE R2 = NULL;

HANDLE R1 = NULL;

#define BUFSIZE 4096

void CreateChildProcess() {
    TCHAR applicationName[] = TEXT("ChildTalk.exe");
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    BOOL success = FALSE;

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

    si.cb = sizeof(STARTUPINFO);
    si.hStdError = W1;
    si.hStdOutput = W1;
    si.hStdInput = R2;
    si.dwFlags |= STARTF_USESTDHANDLES;

    success = CreateProcess(NULL, applicationName, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);

    if (!success) {
        printf("Error creating child process \n");
    }
    else {
        printf("Child process successfuly created \n");
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
}

int main()
{
    printf("Parent process running.... \n");

    DWORD dRead, dWritten;
    CHAR chBuf[BUFSIZE] = "hello";
    BOOL bSuccess = FALSE;

    SECURITY_ATTRIBUTES secAttr;
    secAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
    secAttr.bInheritHandle = TRUE;
    secAttr.lpSecurityDescriptor = NULL;

    printf("Creating first pipe \n");

    if (!CreatePipe(&R1, &W1, &secAttr, 0)) {
        printf("\n error creating first pipe \n");
    }
    printf("Creating second pipe \n");

    if (!CreatePipe(&R2, &W2, &secAttr, 0)) {
        printf("\n error creating second pipe \n");
    }

    if (!SetHandleInformation(R1, HANDLE_FLAG_INHERIT, 0)) {
        printf("\n R1 SetHandleInformation \n");
    }
    if (!SetHandleInformation(W2, HANDLE_FLAG_INHERIT, 0)) {
        printf("\n W1 SetHandleInformation \n");
    }

    printf("\n Creating child process..... \n");

    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
    CreateChildProcess();
    for (;;) {
        printf("Inside for loop \n");

        //1. read from stdin
        bSuccess = ReadFile(hStdIn, chBuf, BUFSIZE, &dRead, NULL);
        if (!bSuccess) {
            printf("error reading \n");
            break;
        }

        //2. write to Pipe2
        bSuccess = WriteFile(W2, chBuf, 100, &dWritten, NULL); 
        if (!bSuccess) {
            printf("error reading \n");
            break;
        }

        //3. read from Pipe1
        bSuccess = ReadFile(R1, chBuf, BUFSIZE, &dRead, NULL);
        if (!bSuccess) {
            printf("error reading \n");
            break;
        }

        //4. write to stdout
        bSuccess = WriteFile(hStdOut, chBuf, 100, &dWritten, NULL);
        if (!bSuccess) {
            printf("error reading \n");
            break;
        }
    }
    return 0;
}

И его логический процесс: enter image description here

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