#include <iostream>
#include <windows.h>
#include <string>
#include <thread>
#include <locale>
#include <codecvt>
using namespace std;
// 辅助函数:宽字符转字符串(用于打印/调试)
string WstringToString(const wstring& wstr) {
wstring_convert<codecvt_utf8<wchar_t>> conv;
return conv.to_bytes(wstr);
}
// 读取管道内容的辅助函数(增加错误处理)
void ReadPipe(HANDLE hPipe, string& output) {
char buffer[4096];
DWORD bytesRead = 0;
DWORD errCode = 0;
// 设置管道非阻塞读取(避免无输出时一直阻塞)
DWORD mode = PIPE_NOWAIT;
SetNamedPipeHandleState(hPipe, &mode, NULL, NULL);
while (true) {
BOOL ret = ReadFile(hPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL);
errCode = GetLastError();
// 无数据可读且管道未关闭:短暂休眠后重试
if (!ret && errCode == ERROR_NO_DATA) {
Sleep(100);
continue;
}
// 读取成功且有数据:追加到输出
if (ret && bytesRead > 0) {
buffer[bytesRead] = '\0';
output += buffer;
cout << "[外部程序输出] " << buffer << flush; // flush确保实时输出
}
// 读取完成(管道关闭/无更多数据)
if ((!ret && errCode == ERROR_BROKEN_PIPE) || (ret && bytesRead == 0)) {
break;
}
}
}
int main()
{
// 1. 定义命令行(正确的宽字符格式,避免强制转换)
wstring cmdWstr = L"\"C:\\Users\\demo.exe\" \"C:\\999-07-25-09-"";
LPWSTR cmdLine = const_cast<LPWSTR>(cmdWstr.c_str()); // 转为可写宽字符指针
// 打印命令行(调试用,确认路径无错)
cout << "开始执行指令:" << WstringToString(cmdWstr) << endl;
// 2. 创建匿名管道
HANDLE hReadPipe, hWritePipe;
SECURITY_ATTRIBUTES sa = { 0 };
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) {
cout << "创建管道失败,错误码:" << GetLastError() << endl;
return 1;
}
// 3. 设置启动信息
STARTUPINFOW si = { 0 };
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; // 隐藏窗口(替代CREATE_NO_WINDOW)
si.hStdOutput = hWritePipe;
si.hStdError = hWritePipe;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
// 4. 启动外部进程
PROCESS_INFORMATION pi = { 0 };
BOOL success = CreateProcessW(
NULL, // 程序名(从cmdLine中解析)
cmdLine, // 完整命令行(宽字符,无强制转换)
NULL, NULL,
TRUE, // 允许继承句柄(关键!)
0, // 取消CREATE_NO_WINDOW,改用si.wShowWindow
NULL, NULL,
&si, &pi
);
if (!success) {
cout << "启动外部程序失败,错误码:" << GetLastError() << endl;
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
// 错误码对照:2=文件不存在,5=权限不足,123=路径/参数格式错
return 1;
}
// 5. 关闭管道写端(子进程已继承,当前进程无需保留)
CloseHandle(hWritePipe);
// 6. 读取管道内容
string outputContent;
thread readThread(ReadPipe, hReadPipe, ref(outputContent));
// 7. 等待外部程序执行完毕(超时保护:30秒)
DWORD waitRet = WaitForSingleObject(pi.hProcess, 30000); // 30秒超时
if (waitRet == WAIT_TIMEOUT) {
cout << "\n警告:外部程序执行超时(30秒),强制结束进程!" << endl;
TerminateProcess(pi.hProcess, 1);
}
// 8. 等待读取线程结束,清理资源
readThread.join();
CloseHandle(hReadPipe);
// 9. 获取退出码并释放句柄
DWORD exitCode;
GetExitCodeProcess(pi.hProcess, &exitCode);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
// 10. 输出结果
cout << "\n===== 外部程序执行完成 =====" << endl;
cout << "退出码:" << exitCode << endl;
if (outputContent.empty()) {
cout << "捕获的输出内容:无(外部程序未输出任何内容,或启动失败)" << endl;
}
else {
cout << "捕获的输出内容:\n" << outputContent << endl;
}
FILE* fp = fopen("D:\\2222.txt", "w");
fwrite(outputContent.c_str(), 1, outputContent.size(), fp);
int ret = fclose(fp);
ret = 100;
return 0;
}
C++执行指令,接收数据
于 2026-03-17 11:34:46 首次发布

2372

被折叠的 条评论
为什么被折叠?



