【发布时间】:2020-09-03 06:20:28
【问题描述】:
我的问题是我无法使用管道从命令行获取输出。
我的任务:“将命令输入流重定向到 cmd.exe | 将 cmd.exe 命令的结果输出到主进程。”
#include <iostream>
#include <windows.h>
using namespace std;
#define deffBuffSize 1024
int funSC() {
HANDLE writeToCL, readFromCL, writeToProcess, readFromProcess;
char lpCmdLine[] = "cmd.exe /k ipconfig";
STARTUPINFOA siA;
PROCESS_INFORMATION piApp;
SECURITY_ATTRIBUTES secAttr;
ZeroMemory(&secAttr, sizeof(SECURITY_ATTRIBUTES));
ZeroMemory(&siA, sizeof(STARTUPINFOA));
secAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
secAttr.lpSecurityDescriptor = NULL;
secAttr.bInheritHandle = TRUE;
if (CreatePipe(&readFromCL, &writeToProcess, &secAttr, 0) == 0) {
cout << "Create pipe error :: " << GetLastError() << endl;
return 1;
}
if (!SetHandleInformation(writeToProcess, HANDLE_FLAG_INHERIT, 0)) {
cout << "SetHandleInformation error :: " << GetLastError() << endl;
}
if (CreatePipe(&readFromProcess, &writeToCL, &secAttr, 0) == 0) {
cout << "Create pipe error :: " << GetLastError() << endl;
return 1;
}
if (!SetHandleInformation(readFromProcess, HANDLE_FLAG_INHERIT, 0)) {
cout << "SetHandleInformation error :: " << GetLastError() << endl;
}
siA.cb = sizeof(STARTUPINFOA);
siA.hStdInput = readFromProcess;
siA.hStdOutput = writeToProcess;
siA.hStdError = writeToProcess;
siA.dwFlags = STARTF_USESTDHANDLES;
if (CreateProcessA(NULL, lpCmdLine, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &siA, &piApp) == 0) {
cout << "CreateProcessA error :: " << GetLastError() << endl;
return 1;
}
else {
CloseHandle(readFromProcess);
CloseHandle(writeToProcess);
}
DWORD dRead = 0;
char chBuff[deffBuffSize];
bool bSuccess = FALSE;
memset(chBuff, '\0', deffBuffSize);
string outStd;
bSuccess = ReadFile(readFromCL, chBuff, deffBuffSize, &dRead, NULL);
cout << "bSuccess: " << bSuccess << endl;
cout << "GetLastError: " << GetLastError() << endl;
cout << "Message: " << chBuff;
//CloseHandle(writeToCL);
//CloseHandle(readFromCL);
CloseHandle(piApp.hProcess);
CloseHandle(piApp.hThread);
return 0;
}
int main() {
int result = 0;
result = funSC();
system("pause");
return result;
}
当我执行 ReadFile() 时,我得到了结果。 ERROR_BROKEN_PIPE (109) - 管道已结束。 据我了解,管道在录制结束时关闭 => 问题:“为什么 CreateProcess() 应该执行“ipconfig”而不是将其输出到覆盖的输出流。”
我阅读了MSDN,尝试使用现成的代码(为了理解),但这并没有带来积极的结果。
请帮帮我,如果我知道如何解决这个问题,我会很高兴=)
PS:我不能“关闭”控制台窗口,因为我必须有一个有效的目录(例如:cd anyFolder)如果我关闭进程,我将丢失用户所在的目录通过了。
这就是我尝试从管道中读取的方式
for (;;) {
bSuccess = ReadFile(readFromCL, chBuff, deffBuffSize, &dRead, NULL);
if (!bSuccess || dRead == 0) {
break;
}
else {
cout << "Message: " << chBuff;
}
}
这个无限循环没有读取任何内容。
P.S : 这是一个正在运行的程序的输出,但它只输出了一行“ipconfig”命令
【问题讨论】:
-
作为这里的新用户,请拨打tour并阅读How to Ask。关于您的问题,有两个注意事项:它缺少minimal reproducible example,并且不清楚您的问题是特定于 cmd.exe 还是发生在任何控制台应用程序上。
-
@UlrichEckhardt 在你面前,你看到了我需要的真实代码。至于其他控制台应用程序,除了 cmd .exe 之外我没有做过测试
-
@UlrichEckhardt 或者你是什么意思?
-
该代码不能用于重现您的问题,它甚至没有
main()等,因此无法编译。你的任务是在你输入问题之前从代码中删除任何不必要的内容以发布到这里,作为缩小问题范围的一种手段。 -
SetHandleInformation(writeToProcess, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT),也将最后一个参数设置为HANDLE_FLAG_INHERIT。并将secAttr的初始化放在调用CreatePipe之前。然后它对我有用。