我正在使用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”,但仍然没有子进程。我需要首先启动子进程的控制台应用程序吗?
答案 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;
}