用管道将cmd.exe信息输出到窗口

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
void CParentDlg::OnBnClickedButton3()
{
//创建管道
SECURITY_ATTRIBUTES sa = {};
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
::CreatePipe(&m_hSelfRead, &m_hCmdWrite, &sa, 0);
::CreatePipe(&m_hCmdRead, &m_hSelfWrite, &sa, 0);

//创建子进程
STARTUPINFO si = {};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = m_hCmdRead;
si.hStdOutput = m_hCmdWrite;

PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
"cmd.exe", // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
TRUE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}


void CParentDlg::OnBnClickedButton4()
{
CString strBuf;
GetDlgItemText(EDT_COMD, strBuf);
strBuf += "\r\n";
BOOL bRet = WriteFile(m_hSelfWrite, strBuf.GetBuffer(), strBuf.GetLength(), NULL, NULL);
if (!bRet)
{
AfxMessageBox("写入管道失败");
}
}


void CParentDlg::OnBnClickedButton5()
{
DWORD dwBytesAvail = 0;
BOOL bRet = ::PeekNamedPipe(m_hSelfRead, NULL, 0, NULL, &dwBytesAvail, NULL);
if (!bRet)
{
AfxMessageBox("无法查看管道剩余数据");
return;
}
//管道中有数据再读
if (dwBytesAvail > 0)
{
CString strBuf;
DWORD dwBytesToRead = 0;
BOOL bRet = ::ReadFile(
m_hSelfRead,
strBuf.GetBufferSetLength(MAXBYTE),
MAXBYTE,
&dwBytesToRead,
NULL
);
if (!bRet)
{
AfxMessageBox("读取数据失败");
return;
}
strBuf.ReleaseBuffer(dwBytesToRead);
SetDlgItemText(EDT_SHOW, strBuf);
}
}

分析:

1
2
3
4
5
6
7
8
9
::CreatePipe(&m_hSelfRead, &m_hCmdWrite, &sa, 0);		
::CreatePipe(&m_hCmdRead, &m_hSelfWrite, &sa, 0);

//创建子进程
STARTUPINFO si = {};
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = m_hCmdRead;
si.hStdOutput = m_hCmdWrite;

第一个管道:::CreatePipe(&m_hSelfRead, &m_hCmdWrite, &sa, 0);

  • **m_hSelfRead**:父进程读取句柄。父进程通过这个句柄从管道中读取数据,即从子进程 cmd.exe 的输出中读取数据。
  • **m_hCmdWrite**:子进程写入句柄。子进程通过这个句柄向管道中写入数据,即将 cmd.exe 的输出写入管道。

第二个管道:::CreatePipe(&m_hCmdRead, &m_hSelfWrite, &sa, 0);

  • **m_hCmdRead**:子进程读取句柄。子进程通过这个句柄从管道中读取数据,即从父进程输入的数据。
  • **m_hSelfWrite**:父进程写入句柄。父进程通过这个句柄向管道中写入数据,即将命令输入到 cmd.exe

STARTUPINFO 结构体中,si.hStdInputsi.hStdOutput 应该分别设置为用于输入和输出的管道句柄,以便父进程可以通过这些句柄与子进程 cmd.exe 进行通信。正确的设置方式:

  1. **si.hStdInput**:设置为子进程的读取句柄 m_hCmdRead(由句柄m_hSelfWrite写入,m_hCmdRead在子进程读出)这意味着子进程将从此管道读取数据。
  2. **si.hStdOutput**:设置为子进程的写入句柄 m_hCmdWrite(由句柄m_hCmdWrite写入,由m_hSelfRead在父进程读出),这意味着子进程将把输出数据写入此管道。