【问题标题】:WINAPI CreateProcess child process is not runningWINAPI CreateProcess 子进程未运行
【发布时间】:2018-12-03 12:15:31
【问题描述】:

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

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

我正在尝试使用管道在父进程和子进程之间创建连接,在这些管道中它们能够相互读写 StdOut。在我的解决方案中,我创建了两个名为 ParentTalk 和 ChildTalk 的控制台应用程序。

据我所知,子进程没有运行我为其创建的代码,因此我可能错误地创建了子进程

父.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:更改了代码,因为我认为句柄不正确,现在它正在打印“内部 for 循环”,但仍然没有子进程。需要先启动子进程的控制台应用吗?

【问题讨论】:

  • 你得到什么输出?请edit您的问题并在那里进行说明
  • 双方先致电ReadFile之前 ant WriteFile。因为您使用 同步 文件 - 您从双方都挂在电话 ReadFile 中。您需要或使用异步管道(最好的)或协调读/写操作。严格按照顺序进行。同样在异步管道的情况下 - 你不需要创建 2 个管道对(4 个句柄)。足够创建单个管道对(仅 2 个句柄 - 1 个在父级和一个在子级)并将此管道用于读取和写入
  • 你想要什么?你必须在ReadFile电话中挂在两边
  • @RbMm 我想要完成的是在孩子的 StdOut 上显示在父母的 StdIn 上写的内容,并在父母的 StdOut 上显示在孩子的 StdIn 上写的内容。子进程代码有一个错误,因为我正在读取孩子的 StdIn 中的内容并将其写入孩子的 StdOut
  • @KushQQ 为子进程打开一个新的控制台,你应该使用标志CREATE_NEW_CONSOLE:CreateProcess(NULL, applicationName, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &amp;si, &amp;pi);

标签: c++ windows winapi process


【解决方案1】:

您的代码中有一些错误。

首先,

childOutRead = GetStdHandle(STD_OUTPUT_HANDLE); parentInRead = GetStdHandle(STD_INPUT_HANDLE); 从 CreatePipe 获得的 2 句柄已重置为 stdhandle,并且丢失了管道句柄。

第二,

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

应该是CreatePipe(&amp;childOutRead, &amp;childOutWrite, &amp;secAttr, 0)

第三,

SetHandleInformation() 中的句柄不正确。

好吧,让我们返回您的问题。

为了隐藏子进程,它的stdin/stdout句柄被设置为管道句柄,所以你看不到控制台,但它确实在后台运行。 我对您的示例做了一些更改(为简单起见,不使用异步):

父.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;
}

及其逻辑过程:

【讨论】:

  • 现在我只能使用其中一个管道我需要评论另一个管道,即我可以从 Parent StdIn 读取并在 Child StdOut 上写入,或者相反但是不是同时。是因为我试图从两个管道中读取吗?还是孩子的 StdIn 和 StdOut 的句柄不正确
  • 同时写入两个管道并不重要。但是如果同时读取,并且每个管道都没有数据,那么这2个进程就会卡住。这个变量(childInRead)只是被初始化了。所以孩子的 StdOut 和 StdError 的句柄总是等于 NULL ,您可以将我的代码与您的代码进行比较,看看我没有指出的差异。
  • 唯一不符合您要求的是无法在子进程中显示消息。或者您可以使用命名管道与子进程进行通信。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-04
  • 2011-04-17
  • 2020-02-26
  • 1970-01-01
  • 1970-01-01
  • 2015-06-23
  • 1970-01-01
相关资源
最近更新 更多