WINAPI CreateProcess子进程未运行

时间:2018-12-03 12:15:32

标签: c++ windows winapi process

我正在使用msdn creating child process中的文章,因为它与我想要实现的目标非常接近。

creating a child process c#redirection using pipes中的问题 在我的方法上发现了一些错误是很有帮助的,但很可能比我能找到的错误更多。

我正在尝试使用管道在父进程和子进程之间建立连接,使它们能够互相读写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:更改了代码,因为我认为Handles不正确,现在它正在打印“ Inside for loop”,但仍然没有子进程。我需要首先启动子进程的控制台应用程序吗?

1 个答案:

答案 0 :(得分:0)

您的代码中有一些错误。

首先

childOutRead = GetStdHandle(STD_OUTPUT_HANDLE); parentInRead = GetStdHandle(STD_INPUT_HANDLE); 从CreatePipe获取的2句柄已被重置为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