1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/**
* @file SendPoint.cpp
* @author DennisMi (https://www.dennisthink.com/)
* @brief
* @version 0.1
* @date 2019-05-12
*
* @copyright Copyright (c) 2019
*
*/
#include<iostream>
#include<Windows.h>
int main()
{
//子进程的输入句柄,绑定到子进程的std::cin
HANDLE hRead=INVALID_HANDLE_VALUE;
//子进程的输出句柄,绑定到子进程的std::cout
HANDLE hWrite=INVALID_HANDLE_VALUE;
//父进程的读取句柄和子进程的输出句柄绑定到一个管道
//绑定 hRead
HANDLE hParentRead=INVALID_HANDLE_VALUE;
//父进程的写入句柄和子进程的输入句柄绑定到一个管道
//绑定 hParentWrite
HANDLE hParentWrite=INVALID_HANDLE_VALUE;
STARTUPINFO stiConsole;
SECURITY_ATTRIBUTES segConsole;
PROCESS_INFORMATION priConsole;
segConsole.nLength = sizeof(segConsole);
segConsole.lpSecurityDescriptor = NULL;
segConsole.bInheritHandle = TRUE;
//构建输入输出句柄的关联
BOOL bFirst = CreatePipe(&hRead, &hParentWrite, &segConsole, 0);
BOOL bSecond = CreatePipe(&hParentRead, &hWrite, &segConsole, 0);
if (bFirst && bSecond)
{
FillMemory(&stiConsole, sizeof(stiConsole), 0);
stiConsole.cb = sizeof(stiConsole);
stiConsole.hStdInput = hRead;
stiConsole.hStdOutput = hWrite;
stiConsole.hStdError = hWrite;
stiConsole.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
stiConsole.wShowWindow = SW_SHOW; // execute hide
DWORD nWriteLen = 0;
char buff[512] = { 0 };
DWORD nReadLean = 0;
DWORD nReadAval = 0;
std::string strBuf = "Hello\r\n";
//创建子进程
if (CreateProcess("RecvPoint.exe",
NULL,
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE,
NULL,
NULL, &stiConsole, &priConsole) == TRUE)
{
//等待子进程启动
Sleep(5000);
for(int i = 0 ; i 100 ; i++)
{
//检查可读管道内是否有数据
if (!PeekNamedPipe(hParentRead, NULL, NULL, &nReadLean, &nReadAval, NULL) || nReadAval = 0)//PeekNamePipe用来预览一个管道中的数据,用来判断管道中是否为空
{
std::cout<< "Break " << __LINE__ << std::endl;
break;
}
memset(buff, 0, 512);
//读取子进程的输出
if (ReadFile(hParentRead, buff, 512, &nReadLean, NULL))//这里是读管道,即便已经没有数据,仍然会等待接收数据,因为,子进程会认为父进程仍有数据要发送,只是暂时没法送,
{ //所以,会“卡”在这里。所以才需要PeekNamePipe
if (nReadLean == 0)
{
std::cout << "Break " << __LINE__ << std::endl;
break;
}
std::cout << "Read : " << buff << " " nReadLean << std::endl;
}
//将数据写入子进程
WriteFile(hParentWrite, strBuf.c_str(), strBuf.length(), &nWriteLen, 0);
Sleep(1000);
}
}
}
//关闭相应的句柄
std::cout << TerminateProcess(priConsole.hProcess, 0) << std::endl;;
std::cout << CloseHandle(priConsole.hProcess);
std::cout << CloseHandle(priConsole.hThread);
std::cout << CloseHandle(hRead);
std::cout << CloseHandle(hWrite);
std::cout << CloseHandle(hParentRead);
std::cout << CloseHandle(hParentWrite);
}
|