C++学习:通过管道进行cmd进程输入输出重定向

VC调用cmd进行交互(双管道) void CLikeCmdDlg::OnBtnExe() { // TODO: Add your control notification handler code here UpdateData(); CString cs(m_childProcess); cs += m_cmd; LPTSTR lpsz = (LPTSTR)(LPCTSTR)cs; 阅读详情

在日常的工作中,shell使用比较多,尤其在软件测试过程中,但使用手工操作既麻烦,又记不住命令,关键是不能自动化。众所周知,linux或者windows系统的shell都是可以进行输入输出重定向的,利用输入输出重定向技术,把shell的输入输出映射到自己所写的进程里,这样就很方面了。比如要使用ssh2远程一个linux机器,就需要自己实现ssh2客户端的协议,使用重定向,就可以直接使用操作系统自带的ssh(linux系统),或者putty(windows下的telnet、ssh命令)。


本文所要讲述的实现方法就是利用管道,管道的概念,大家网上搜索,这里还是通过直接show代码的方式进行讲述,另外进行了简单的封装和进一步的抽象,大家可以直接使用,扩展起来也比较方便。本文是基于win32,linux实现留给大家自己当着作业吧,于此类似。


首先设计Shell类型的大概的样子如下:

#include "windows.h"

class Shell
{
public:
	Shell(void);
	~Shell(void);

	bool RunProcess(const string &process);
	bool StopProcess(void);
	bool GetOutput(const string &endStr, int timeout, string &outstr );//获取输出字符串
	bool SetInput(const string &cmd);//执行命令
private:
	HANDLE m_hChildInputWrite;	//用于重定向子进程输入的句柄
	HANDLE m_hChildInputRead;
	HANDLE m_hChildOutputWrite;	//用于重定向子进程输出的句柄  
	HANDLE m_hChildOutputRead;
	PROCESS_INFORMATION m_cmdPI;//cmd进程信息
};
上述代码,重定向的句柄保存起来,目的是方便用户自己扩展,同时也保存了cmd进程的信息,可以在程序推出的时候,杀掉cmd进程。接下来看看构造函数和析构函数,资源初始化和释放。

Shell::Shell(void)
{
	m_hChildInputWrite = NULL;
	m_hChildInputRead  = NULL;
	m_hChildOutputWrite= NULL;
	m_hChildOutputRead = NULL;
	ZeroMemory(&m_cmdPI, sizeof(m_cmdPI));   
}

Shell::~Shell(void)
{
	StopProcess(); 
}

接下来就是创建进程(比如cmd.exe)了,便于进行输入输出操作,代码如下:

bool Shell::RunProcess( const string &process )
{
	SECURITY_ATTRIBUTES   sa;   
	sa.bInheritHandle = TRUE;   
	sa.lpSecurityDescriptor = NULL;   
	sa.nLength = sizeof(sa); 

	//创建子进程输出匿名管道 
	if( FALSE == ::CreatePipe(&m_hChildOutputRead, &m_hChildOutputWrite, &sa, 0) )   
	{    
		return false;   
	}  

	//创建子进程输入匿名管道   
	if( FALSE == CreatePipe(&m_hChildInputRead, &m_hChildInputWrite, &sa, 0) )   
	{   
		::CloseHandle(m_hChildOutputWrite);
		::CloseHandle(m_hChildOutputRead);
		::CloseHandle(m_hChildOutputWrite);
		::CloseHandle(m_hChildOutputRead);
		return false;
	}

	ZeroMemory(&m_cmdPI, sizeof(m_cmdPI));   
	STARTUPINFO  si; 
	GetStartupInfo(&si);

	si.cb = sizeof(STARTUPINFO);
	si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;
	si.hStdInput   = m_hChildInputRead;     //重定向子进程输入   
	si.hStdOutput  = m_hChildOutputWrite;   //重定向子进程输入    
	si.hStdError   = m_hChildOutputWrite; 

	if( FALSE == ::CreateProcess(NULL, (process.c_str()), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &m_cmdPI) )   
	{   
		::CloseHandle(m_hChildInputWrite);
		::CloseHandle(m_hChildInputRead);
		::CloseHandle(m_hChildOutputWrite);
		::CloseHandle(m_hChildOutputRead);
		m_hChildInputWrite = NULL;
		m_hChildInputRead  = NULL;
		m_hChildOutputWrite= NULL;
		m_hChildOutputRead = NULL;
		ZeroMemory(&m_cmdPI, sizeof(m_cmdPI));  
		return false;   
	}

	return true;
}

bool Shell::StopProcess( void )
{
	::CloseHandle(m_hChildInputWrite);
	::CloseHandle(m_hChildInputRead);
	::CloseHandle(m_hChildOutputWrite);
	::CloseHandle(m_hChildOutputRead);
	m_hChildInputWrite = NULL;
	m_hChildInputRead  = NULL;
	m_hChildOutputWrite= NULL;
	m_hChildOutputRead = NULL;
	::TerminateProcess(m_cmdPI.hProcess, -1);
	::CloseHandle(m_cmdPI.hProcess);   
	::CloseHandle(m_cmdPI.hThread); 
	ZeroMemory(&m_cmdPI, sizeof(m_cmdPI));
}

如果你想通过putty来实现telnet、ssh操作进行,一是把cmd.exe替换为putty命令行的形式,另外一种形式,就是把putty当着普通的shell命令执行即可。进程创建好了,下面来看看读写函数的实现:

bool Console::GetOutput( const string &endStr, int timeout, string &outstr )
{
	if( NULL == m_hChildOutputRead )
	{
		return false;
	}

	outstr = "";
	char buffer[4096] = {0};
	DWORD readBytes = 0;
	while( timeout > 0 )
	{
		//对管道数据进行读,但不会删除管道里的数据,如果没有数据,就立即返回
		if( FALSE == PeekNamedPipe( m_hChildOutputRead, buffer, sizeof(buffer) - 1, &readBytes, 0, NULL ) )
		{
			return false;
		}

		//检测是否读到数据,如果没有数据,继续等待
		if( 0 == readBytes )
		{
			::Sleep(200);
			timeout -= 200;
			continue;
		}
		
		readBytes = 0;
		if( ::ReadFile( m_hChildOutputRead, buffer, sizeof(buffer) - 1, &readBytes, NULL) )
		{
			outstr.insert( outstr.end(), buffer, buffer + readBytes );
			size_t pos = outstr.rfind(endStr);
			if( string::npos == pos )
			{
				continue;
			}
			if( pos == outstr.size() - endStr.size() )
			{
				return true;//找到数据
			}
		}
		else
		{
			return false;
		}
	}

	return false;
}

bool Shell::SetInput( const string &cmd )
{
	if( NULL == m_hChildInputWrite )
	{
		return "";
	}

	string tmp = cmd + "\r\n";
	DWORD writeBytes = 0;
	if( FALSE == ::WriteFile( m_hChildInputWrite, tmp.c_str(), tmp.size(), &writeBytes, NULL ) )
	{
		return false;
	}
	return true;
}

写函数实在是平淡无奇,就是调用WriteFile,只要把句柄传递对了就行,这几个句柄是容易混淆,大家仔细阅读代码,仔细理解。在读函数中,使用了PeekNamedPipe函数,对管道进行数据读,这个函数有个作用,即使管道中没有数据,但会立即返回,不会读阻塞。这个时候再调用ReadFile就不会阻塞了。同时,使用Sleep函数就能简单的实现超时读的功能。这个是ReadFile办不到的。


到此为止,代码已经实现完了,很简单吧,曾经为了实现ssh2客户端,费尽心思,找了无数个开源代码研究。用这个方法来实现,真是太简单了。不是吗?下面来看看测试代码:

#include "console.h"
#include <iostream>
using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
	Console console;
	if( false == console.RunProcess("cmd.exe") )
	{
		cout<<"create cmd.exe process fail"<<endl;
		return -1;
	}
	string outstr;
	console.GetOutput(">", 3000, outstr);
	cout<<outstr<<endl;
	console.SetInput("dir");
	console.GetOutput(">", 3000, outstr);
	cout<<outstr<<endl;

	return 0;
}

上述代码输出:



大功告成,代码实现没有用到什么高级技巧,但简单适用,大家不妨直接借用,也许能帮助大家解决日常的工作问题。


Windows CMD命令大全:从基础操作到高级运维实战指南 命令行界面(CLI)作为操作系统与用户交互的核心方式,通过文本指令直接调用系统功能。其工作原理是基于命令解释器解析用户输入,执行对应的系统调用或程序。在技术价值层面,命令行工具具有执行效率高、资源占用少、可批量自动化等优势,特别适合系统管理、网络调试和运维自动化场景。以Windows CMD命令为例,ping和ipconfig等网络命令能够快速诊断连通性问题,taskkill和tasklist可实现精准的进程管理,而批处理脚本更能将多个命令组合成自动化流程。掌握这些基础命令不仅能提升日常工作效率,更是进阶学 阅读详情

相关推荐

C++编程:使用boost::process::cmd进行进程操作的示例程序

首先,我们包含了必要的头文件,包括iostream、string和boost/process.hpp。在循环体中,我们打印每一行的内容,并在行末尾添加换行符。执行命令并获取输出,你可以根据自己的实际需求进行进一步的定制和扩展。,它存储了我们要执行的命令。在这个示例中,我们使用了一个简单的命令。变量的值,以执行不同的命令并捕获其输出。管道流中获取输出内容,并将其打印到标准输出。是一个输入流,它允许我们从子进程中读取输出内容。最后,我们返回0,表示程序成功执行完毕。,它将被用于捕获子进程的输出。

2301_79325339的博客 353

c++ 执行命令行获取执行结果

最早用了一种方法, , cmd.exe /c 命令 , 结合 单管道重定向输出信息来dos命令输出结果, 但这种方法在命令比较复杂(夹杂多个空格, 双引号) 的情况 会导致cmd.exe无法正确解析出要执行的命令, 出现命令传递错误, 执行失败. 命令格式参见帮助:dos下执行 cmd /?之后用双管道, 重定向命令输入和命令结果输出, 把命令通过输入管道写入cmd.exe进程并执行,

vbbianchengde的专栏 6237

VC++实现使用管道重定向进程输入输出(附完整源码)

VC++实现使用管道重定向进程输入输出(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 419

C/C++利用管道机制实现输出重定向功能

#include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<signal.h> #include <string> using

qq_25048473的博客 954

C#实现CMD命令执行与输出捕获

C#(读作“C Sharp”)是微软公司开发的一种现代、类型安全的面向对象编程语言。它源自C和C++语言,具有清晰的语法结构和丰富的类库支持,使得开发者可以快速构建各种应用程序,包括Windows客户端应用程序、游戏、Web应用、移动应用以及云计算服务。C#语言的最新版本不断引入新的编程范式和技术,如异步编程、LINQ和模式匹配等,以适应日益变化的软件开发需求。

weixin_32242475的博客 1311

Windows平台下Linux命令接口设计与实现:C++与Win32 API课程设计指南

在Windows环境下模拟Linux命令接口,核心在于通过系统编程实现命令解析与执行。其原理是利用Win32 API直接操作文件、进程和系统信息,避免依赖外部shell,从而构建原生接口层。这种技术方案不仅提升了系统编程能力,还增强了跨平台命令的兼容性。典型应用场景包括操作系统课程设计、系统编程毕设以及命令行工具开发。通过三层架构(解析、分发、执行)和命令注册表机制,可高效实现ls、cat、grep等常用命令,并处理路径空格、中文乱码等边界问题。本文聚焦于Windows平台下的Linux杂项命令接口设计,提

weixin_42523693的博客 260

[学习]VC++管道技术CreateProcess,pipe cmd回显

////通过管道技术回显cmd输出信息// SECURITY_ATTRIBUTES sa; HANDLE hRead,hWrite;   sa.nLength = sizeof(SECURITY_ATTRIBUTES);  sa.lpSecurityDescriptor = NULL;  //使用系统默认的安全描述符  sa.bInheritHandle = TRUE;  //创建的进

cciey的专栏 8354

VC捕获CMD命令输出:匿名管道与_popen深度实践

在Windows平台进行进程间通信时,命令行输出捕获是系统监控、自动化运维和MFC工具开发的基础能力。其核心原理依赖于操作系统提供的匿名管道机制,通过重定向子进程的标准输入输出句柄实现数据流控制。技术价值体现在绕过system()的黑盒限制,获得结构化、可编码转换、带超时与错误处理的实时文本结果。典型应用场景包括MFC对话框中动态显示ipconfig/netstat结果、后台服务定时采集进程信息、以及PowerShell与CMD混合命令的可靠执行。本文聚焦VC++环境下基于_popen和CreateProc

weixin_31061699的博客 267

DOS重定向与管道

我所知道的重定向和管道就这些了,写了一早晨终于写完了,现在接着睡,希望对大家有用。 这是我学习之中知道的一些关于重定向和管道的知识,并积累的资料,在这里和大家分享。如果说的有不足和错误的地方,请指出。毕竟是交流信息。我这里是从DOS和C语言方面看它,没有太多涉及LINUX中所说的。我想从以下几个方面叙述: 一、     重定向: 所谓重定向,就是不使用系统的标准输入端口、标准输出端口或标准错

beyondlpf的专栏 705

MFC通过管道实现CMD命令返回串

MFC通过管道实现CMD命令返回串,可以看一看学习管道的应用,及实现CMD之间传递

LCD工程师必看:MIPI DSI的LP/HS模式切换全流程拆解(附高通平台实测)

本文为LCD工程师深度解析MIPI DSI接口中低速(LP)与高速(HS)模式切换的全流程。文章结合高通平台实测波形,从协议状态机、时序关键参数到实战调试案例,系统拆解了模式切换的本质、协同机制及常见问题排查方法,重点阐述了LP模式在低功耗控制与HS模式在高速数据传输中的核心作用与切换时序。

weixin_29240711的博客 547

qt获取命linux命令行输出,Qt 获取cmd运行结果

http://www.cnblogs.com/gisbeginner/archive/2012/12/08/2809063.htmlBOOL ExecDosCmd(){#define EXECDOSCMD "ping http://www.baidu.com" //可以换成你的命令SECURITY_ATTRIBUTES sa;HANDLE hRead,hWrite;sa.nLength = siz...

weixin_39637614的博客 1508

多智能体协作的本质是中介者模式,不是多开Agent

多智能体系统并非简单启动多个Agent实例,而是一种受控的、可验证的动态交互过程。其核心原理在于解耦Agent间直接依赖,通过中央中介者统一管理任务分发、协议转换、状态协调与故障兜底。这种架构显著提升系统的可观测性、容错性与可维护性,技术价值体现在强一致性保障(如金融订单原子操作)与灵活自治平衡(如边缘设备轻量协同)。典型应用场景包括电商客服协同、工业巡检调度、飞书/微信多渠道智能服务等。OpenClaw与Hermes Agent正是这一范式的工程落地代表,分别体现强中介与弱中介两种演进路径。

weixin_34151004的博客 361

C++:实现正向CMDShell(附带源码)

C++:实现正向CMDShell(附带源码)

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 710

电子系统设计与创新实践作品:简易电子琴

题目 4:简易电子琴 (1)具有8个音阶按键,每个音阶按键频率如表1所示。 (2)每个按键对应LED显示。 (3)音阶信号经功放连接8欧姆扬声器,输出功率可达1W。 (4)每个音阶输出音量一样。 (5)扬声器输出音量可调节,音量调节分为高、中、低三档,并进行档位显示。

weixin_47510497的博客 2858

Windows安装ros2(Jazzy版本+win10/win11)-1.配置windows终端

更高版本的terminal可能设置里更加丰富, 有默认以管理员身份启动的选项等,可自行配置。打开微软应用商店, 在其中搜索并下载 Terminal 即可(注意别挂梯子)下载并安装, 安装的位置自行替换,建议别放到系统盘中。点击任务栏中的搜索, 输入store。

weixin_48398592的博客 1454

Linux 进程间通信:匿名管道、命名管道、共享内存、消息队列与信号量完全指南

本文总结Linux进程间通信(IPC)的5种主要方式:匿名管道、命名管道、共享内存、消息队列和信号量。重点讲解了匿名管道的原理与使用,包括pipe函数创建管道、fork共享管道、管道读写规则与特性。文章还通过代码示例展示了父子进程通过管道通信的实现方式,并分析了管道在内核中的本质是内存缓冲区+文件描述符。最后介绍了如何用管道构建进程池的进阶应用场景。全文以"Linux一切皆文件"思想贯穿,帮助读者从会用管道到理解其底层原理。

2601_95483298的博客 503

pg lib的信息及产生pg lib的三种方法

pg lib相比basic lib会多几方面pg 信息。除了pg arc(pg pin)以外,liberty还提供电压值,以及pmk cell的power_down_function功能相关信息。1.电压值除了常见的primary pg还有secondary pg和衬底。2.pg arc后端需要去做redhawk功耗分析,需要pg liberty提供pg arc,如果没有pg arc就需要手动去写custom lib代替3.pmk cell的power_down_function。

m0_61544122的博客 595

认识 erlexec:为什么每个 Erlang/OTP 开发者都需要这个终极 OS 进程管理器

erlexec 是一款面向 Erlang/OTP 生态的 OS 进程管理器,让你用轻量级的 Erlang 进程轻松启动、控制并监控操作系统进程:获取退出码与信号、双向链接进程、重定向输出、通过 STDIN 交互,甚至以伪终端运行交互式命令。如果你正在写 Erlang 或 Elixir 系统,需要可靠地调用外部命令,它就是那个"终极"答案。 [![erlexec OS 进程管理器主题横幅:Erla

gitblog_00654的博客 296

15、目标检测模型的评估指标与YOLO算法解析

本文详细解析了目标检测模型的评估指标,包括精确率、召回率、AP、mAP及IoU的定义与作用,并深入介绍了YOLO算法的核心原理与推理流程。从网格划分、锚框引入到边界框细化与后处理,全面阐述了YOLO如何实现快速准确的目标检测。同时总结了YOLO在智能安防、自动驾驶和工业检测等领域的应用,并展望了其未来在准确性提升、多类别支持和技术融合方面的发展趋势。

work3的博客 66

【硬刚Hive】HIVE基础(20):Hive函数(9) over 窗口函数

欢迎关注博客主页:微信搜:import_bigdata,大数据领域硬核原创作者_王知无(import_bigdata)_优快云博客 欢迎点赞、收藏、留言 ,欢迎留言交流!本文由【王知无】原创,首发于 优快云博客!本文首发优快云论坛,未经过官方和本人允许,严禁转载! 本文是对《【硬刚大数据之学习路线篇】从零到大数据专家的学习指南(全面升级版)》的Hive部分补充。 hive窗口函数语法 在前言中我们已经说了avg()、sum()、max()、min()是分析函数,而over()才是窗..

微信搜:import_bigdata,大数据领域硬核原创作者 888

C++ (week4):Linux基础:命令行

Linux简介、vim、Linux命令行、编译工具链

Edward2022的博客 1722

Redhawk: dynamic ir drop分析(Clock Buffer Clustering)

在dynamic分析中,ir drop问题多出现在三种情况下,缺power mesh,缺power switch,clock cell过于密集。 前两种情况通过选中具体instance查看min res path都比较容易分析出来,而且大部分问题都出现在channel里,这里不多做赘述。 clock cell过于密集这是观察结果,缺少报告支持,这里分享一下分析方法。 首先,选中压降超过signoff标准的instance,(Results->List of Worst Instance DVD中

m0_61544122的博客 5274

C C++最全【操作系统】总结(二)linux指令_脚本里面 cat 之后添加管道符,C C++推送技术解析

在进程中,TTY指的是与该进程相关联的终端设备。比如一个应用,临时需要高级权限,可以利用交互界面(比如让用户输 入 root 账户密码)验证身份,然后执行需要高级权限的操作,然后马上恢复到普通权限工作。/代表根目录,每一节目录也用/分开,所以在上图所展示 的/usr/bin/rm中,第一级目录是/根目录,第二级目录是usr目录,第三级是bin目录。管道的作用和分类 : 管道和重定向很像,但是管道是一个连接一个进行计算,重定向是将一个文件的内容定向到另一个文 件,这二者经常会结合使用。User Agent。

2401_84976285的博客 791

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【Linux进程控制(三)】实现自主Shell命令行解释器

然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序并等待这个进程结束。步骤描述1获取命令行2解析命令行3建立一个子进程 (fork)4替换子进程 (execvp)5父进程等待子进程退出 (wait)根据这些思路,和我们前面的学的技术,就可以自己来实现一个shell了。strtok() 按空格分割命令行,将 “命令 参数1 参数2” 变成数组 [“命令”,“参数1”,“参数2”,NULL],并计数参数个数。就像。一个C程序有很多函数组成。

艾莉丝努力练剑的博客,感谢大家一直以来的对艾莉丝的支持和鼓励,uu们如果对C/C++方向感兴趣的话,可以通过艾莉丝主页的微信名片加艾莉丝的好友,和努力练剑的艾莉丝一起加油! 1235

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Windows CMD命令行完全指南:从基础到高级实战

命令行界面(CLI)作为操作系统最底层的交互方式,通过文本指令直接控制系统资源,具有高效、可脚本化的特点。Windows CMD作为经典的命令行解释器,基于DOS命令集构建,支持批处理脚本编写,是系统管理、文件操作和自动化任务的利器。其核心原理是通过解析用户输入的命令字符串,调用对应的可执行程序或内置功能模块。在DevOps和自动化运维场景中,CMD常与PowerShell配合使用,实现系统配置、日志分析和批量操作。本文以Windows环境为例,详解CMD的文件管理、进程控制、网络诊断等200+实用命令,特

weixin_30666401的博客 460

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

上一篇: C++学习:一个简单适用的跨平台Log类(1)
下一篇: C++学习:一个通用ini配置文件操作类
chaos-god
博客等级 码龄20年 39粉丝 47原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值