[VC] 运行并抓取cmd管道的运行反馈

该代码段展示了如何使用Windows API函数CreateProcessA来执行命令(如`dir`),并通过管道读取其输出结果。首先创建管道,然后设置STARTUPINFO结构以重定向进程的标准输出和错误到管道,接着调用CreateProcessA启动命令,读取管道中的数据,并等待进程结束。
BOOL CmdRuner(char *command, char *pOut)
{
	SECURITY_ATTRIBUTES sa;
	HANDLE hRead = NULL, hWrite = NULL;

	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = TRUE;
	if (!CreatePipe(&hRead, &hWrite, &sa, 0))
	{
		return FALSE;
	}
	STARTUPINFOA si;
	PROCESS_INFORMATION pi;
	si.cb = sizeof(STARTUPINFOW);
	GetStartupInfoA(&si);
	si.hStdError = hWrite;
	si.hStdOutput = hWrite;
	si.wShowWindow = SW_HIDE;
	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
	if (!CreateProcessA(NULL, (char *)command, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))
	{
		CloseHandle(hWrite);
		CloseHandle(hRead);
		return FALSE;
	}

	CloseHandle(hWrite);

	char szBuffer[5 * 1024] = {0};
	DWORD dwReaded;
	DWORD dwExitCode;
	char *pTempOut = pOut;
	while (GetExitCodeProcess(pi.hProcess, &dwExitCode))
	{
		if (dwExitCode != STILL_ACTIVE)
		{
			break;
		}

		memset(szBuffer, 0, sizeof(szBuffer));
		if (!ReadFile(hRead, szBuffer, sizeof(szBuffer) - 1, &dwReaded, NULL))
		{
			break;
		}

		memcpy(pTempOut, szBuffer, dwReaded);
		pTempOut += dwReaded;
	}
	

	WaitForSingleObject(pi.hProcess, INFINITE);
	CloseHandle(hRead);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	return TRUE;
}

//---------------使用------------

CString inputStr="dir"; //显示目录

CString strCmd ;

char strOut[10240]={0}; //运行后的结果输出

strCmd .Format( "cmd /c %s ",inputStr);

CmdRuner(strCmd .GetBuffer(),strOut);

=====方案2:与管道双向通讯======

//=========CEnginePipe.cpp===============
#include "pch.h"
#include "CEnginePipe.h"
#include <afxmt.h>

#define PIPE_BUFSIZE (1024 * 5)

static void Trace(CString str)
{
	OutputDebugString(str);
	OutputDebugString("\n");
}


static UINT WINAPI EnginePipeProcThread(LPVOID lpParam)
{
	CEnginePipe *pipe = (CEnginePipe *)lpParam;
	HANDLE hInputWrite, hInputRead;
	HANDLE hOutputWrite, hOutputRead;
	SECURITY_ATTRIBUTES sa;
	PROCESS_INFORMATION pi;
	STARTUPINFO si;

	// 设置安全属性
	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = NULL;

	// 创建用于输出的管道
	if (!CreatePipe(&hOutputRead, &hOutputWrite, &sa, 0))
	{
		Trace("CreatePipe failed! output read err.");
		return 1;
	}

	// 创建用于输入的管道
	if (!CreatePipe(&hInputRead, &hInputWrite, &sa, 0))
	{
		Trace("CreatePipe failed! input read err.");
		return 2;
	}

	// 确保读取句柄不被继承
	SetHandleInformation(hOutputRead, HANDLE_FLAG_INHERIT, 0);
	SetHandleInformation(hInputWrite, HANDLE_FLAG_INHERIT, 0);

	// 设置启动信息
	ZeroMemory(&si, sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);
	si.hStdError = hOutputWrite;
	si.hStdOutput = hOutputWrite;
	si.hStdInput = hInputRead;
	si.dwFlags = STARTF_USESTDHANDLES |STARTF_USESHOWWINDOW;

	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));

	// 创建子进程(这里后台加载exe)
	if (!CreateProcess(NULL, pipe->m_strPipeName.GetBuffer(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
	{
		Trace("CreatePipe failed! create process err.");
		return 3;
	}

	// 关闭不需要的句柄
	CloseHandle(hOutputWrite);
	CloseHandle(hInputRead);

	pipe->m_hInputWrite = hInputWrite;

	// 读取和写入循环
	DWORD dwRead, dwWritten;
	CHAR chBuf[PIPE_BUFSIZE]; 
	BOOL bSuccess = FALSE;
	DWORD bytesAvail = 0;
	while (TRUE)
	{
		// 检查管道中是否有数据
		PeekNamedPipe(hOutputRead, NULL, 0, NULL, &bytesAvail, NULL);
		if (bytesAvail > 0)
		{
			bSuccess = ReadFile(hOutputRead, chBuf, PIPE_BUFSIZE - 1, &dwRead, NULL);
			if (bSuccess && dwRead > 0)
			{
				chBuf[dwRead] = '\0';
				Trace("=======================================");
				Trace(chBuf);
				::SendMessageA(pipe->m_hWnd, WM_ENGINEPIPE_MSG, dwRead, (LPARAM)chBuf);
			}
		}
		else
			Sleep(50);

		// 检查进程是否还在运行
		DWORD exitCode;
		GetExitCodeProcess(pi.hProcess, &exitCode);
		if (exitCode != STILL_ACTIVE)
		{
			break;
		}
	}

	// 清理
	CloseHandle(hOutputRead);
	CloseHandle(hInputWrite);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);

	pipe->m_hInputWrite = NULL;

	Trace("Subprocess exited with code!\n");
	return 0;
}

CEnginePipe::CEnginePipe()
{
	
}

CEnginePipe::~CEnginePipe()
{
}

int CEnginePipe::SendCmd(CString cmdStr)
{
	DWORD dwWritten = 0;
	CString command = cmdStr + "\n";
	WriteFile(m_hInputWrite, command, strlen(command), &dwWritten, NULL);
	return (int)dwWritten;
}

int CEnginePipe::CreateEnginePipe(HWND hWnd,CString strPipeName)
{
	m_hWnd = hWnd;
	m_strPipeName = strPipeName;
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)EnginePipeProcThread,
				 this, 0, NULL);
	return 0;
}
//===============CEnginePipe.h===================
#pragma once

#define WM_ENGINEPIPE_MSG  (WM_USER + 0x1000)
class CEnginePipe
{
	public:
		CEnginePipe();
		~CEnginePipe();
		HANDLE m_hInputWrite;
		CString m_strPipeName;
		HWND m_hWnd;
public:
		int CreateEnginePipe(HWND hWnd,CString strPipeName);
		int CEnginePipe::SendCmd(CString cmdStr);
};

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值