说明,上一次写到了使用共享内存来实现获取命令行的输出。但是共享内存实际上是实现两个进程间的通信。其使用方式为在本进程创建共享内存,并在另外一个进程中调用cmd将结果写入到共享内存中,实际没有处理如何调用命令行的问题,与本文的主题不是特别符合。因此这里将其删去,并增加了使用boost库(因为在项目中使用不方便贴代码,有空的时候另外配环境写个demo)的方法。共享内存的话,就偷个懒转个msdn上的demo,Creating Named Shared Memory - Win32 apps | Microsoft Docs

最近在做C++时遇到了一个棘手的问题,我需要获取组策略中的密码配置策略,但是本地用户没有权限。只能使用转调命令行来获取密码配置的输出,因此对C++中调用命令行的几种方式进行了汇总整理。

1. system,system函数在不同平台下都有实现,但是system函数无法获取cmd执行的结果

#include "stdafx.h"/*** @brief    通过system调用命令行*/
void cmdSystem(const std::string& cmdLine) {system(cmdLine.c_str());
}int main(int argc, char* argv[])
{std::string cmdLine(R"("echo Hello,World!")");cmdSystem(cmdLine);system("pause");return 0;
}

2. _popen,使用匿名管道执行cmd命令并获取执行结果

/*** @brief 通过_popen调用命令行并获取输出结果*/
std::string cmdPopen(const std::string& cmdLine) {char buffer[1024] = { '\0' };FILE* pf = NULL;pf = _popen(cmdLine.c_str(), "r");if (NULL == pf) {printf("open pipe failed\n");return std::string("");}std::string ret;while (fgets(buffer, sizeof(buffer), pf)) {ret += buffer;}_pclose(pf);return ret;
}int main(int argc, char* argv[])
{std::string cmdLine(R"("echo Hello,World!")");// cmdSystem(cmdLine);std::string tmp=cmdPopen(cmdLine);printf("the resule of cmd is %s", tmp.c_str());system("pause");return 0;
}

3.CreateProcess(windows下)

#include <windows.h>/*** @brief   通过CreateProcess调用命令行并获取输出结果*/
std::string cmdProcess(const std::string& cmdLine) {/* 创建匿名管道 */SECURITY_ATTRIBUTES _security = { 0 };_security.bInheritHandle = TRUE;_security.nLength = sizeof(_security);_security.lpSecurityDescriptor = NULL;HANDLE hRead = NULL, hWrite = NULL;if (!CreatePipe(&hRead, &hWrite, &_security, 0)) {printf("创建管道失败,error code=%d \n", GetLastError());}/* cmd命令行转换为Unicode编码 */int convLength = MultiByteToWideChar(CP_UTF8, 0, cmdLine.c_str(), (int)strlen(cmdLine.c_str()), NULL, 0);if (convLength <= 0) {printf("字符串转换长度计算出错\n");}std::wstring wCmdLine;wCmdLine.resize(convLength + 10);convLength = MultiByteToWideChar(CP_UTF8, 0, cmdLine.c_str(), (int)strlen(cmdLine.c_str()), &wCmdLine[0], (int)wCmdLine.size());if (convLength <= 0) {printf("字符串转换出错\n");}/* 创建新进程执行cmd命令并将结果写入到管道 */PROCESS_INFORMATION pi = { 0 };STARTUPINFO si = { 0 };si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;si.wShowWindow = SW_HIDE; // 隐藏cmd执行的窗口si.hStdError = hWrite;si.hStdOutput = hWrite;if (!CreateProcess(NULL,&wCmdLine[0],NULL,NULL,TRUE,0,NULL,NULL,&si,&pi)) {printf("创建子进程失败,error code=%d \n", GetLastError());}/* 等待进程执行命令结束 */::WaitForSingleObject(pi.hThread, INFINITE);::WaitForSingleObject(pi.hProcess, INFINITE);/* 从管道中读取数据 */DWORD bufferLen = 10240;char *buffer =(char*)malloc(10240);memset(buffer, '\0', bufferLen);DWORD recLen = 0;if (!ReadFile(hRead, buffer, bufferLen, &recLen, NULL)) {printf("读取管道内容失败, error code=%d\n", GetLastError());}std::string ret(buffer);/* 关闭句柄 */CloseHandle(hRead);CloseHandle(hWrite);CloseHandle(pi.hProcess);CloseHandle(pi.hThread);free(buffer);return ret;
}int main(int argc, char* argv[])
{std::string cmdLine(R"("ipconfig")");// cmdSystem(cmdLine);//std::string tmp=cmdPopen(cmdLine);std::string tmp = cmdProcess(cmdLine);printf("the resule of cmd is %s", tmp.c_str());system("pause");return 0;
}

4. 使用boost库的child类(过了一年再来填坑)
boost库提供了一个好用的跨平台的方案,实现也相当简单优雅。并且提供进程控制和获取返回值等多种强大功能。具体的功能的话就直接参见boost文档里,这里直接上测试代码和测试结果

#include <iostream>#include <boost/process.hpp>using namespace std;
using namespace boost::process;/*** @brief 启动命令行,并获取命令行的数据*        执行proc1.exe,proc1.exe会输出Hello,proc1*        在当前进程中读取子进程的输出*/
static void startCmd()
{int result = boost::process::system("proc1.exe",        /* 要执行的命令或者程序,如果有参数的话可以在后面追加 */boost::process::std_out > stdout /* 重定向子进程的输出流,方便查看一下输出也可以重定向到当前任何刘或者文件如果要读取数据的话可以直接从流中读取 */);
}/*** @brief 启动子进程,并获取子进程中的数据*/
static void startChildProc()
{boost::process::ipstream is;child c("proc1.exe", boost::process::std_out > is); /* 注意:这里的proc1.exe是实现准备好的一个测试程序会使用std::out输出一些数据z这里重定向到一个流对象,然后逐行读取其输出*/std::vector<std::string> data;std::string line;while (c.running() && std::getline(is, line) && !line.empty())data.push_back(line);c.wait();for (const auto & s : data) {cout << s << endl;}
}int main(int argc, char* argv[])
{cout<<"Hello, proc2"<<endl;cout << "proc2 pid:" << boost::this_process::get_id() << endl;//startCmd();startChildProc();return 0;
}

windows下,C++中调用命令行并且获取命令行的输出相关推荐

  1. C#中调用命令行程序开启wifi热点

    为什么80%的码农都做不了架构师?>>>    最近想在win7上开启wifi热点,于是就弄出下面这个小东西,里面涉及如何在控制台上输入命令,分享一下.首先在VS中创建一个windo ...

  2. 程序中调用命令行命令,不显示那个黑黑的DOS窗口

    From: http://hi.baidu.com/yanqiuge/item/5da466c3d3f18453ad00ef1d 在程序中使用命令行时,会有黑黑的DOS窗口,很不爽,在网上查了一下,写 ...

  3. 【转】[Python Tip]如何在Windows下方便地进入命令行运行程序

    http://blog.donews.com/limodou/archive/2005/10/20/595292.aspx 在windows下的cmd窗口中执行python程序 ,我一般是这样做: 1 ...

  4. Windows下dos中 copy命令的实现

    实现的的功能:复制文件功能 一:功能分析 1.1windows 系统下的 dos命令中 指令 copy 能实现文件的复制. 比如: copy log.txt log1.txt 就是将log.txt 文 ...

  5. Windows下cmd中cd命令不起作用的原因和解决办法

    问题如图: 即便是输入了cd指令,但是并没有跳转. 原因: 实际上cmd换目录跨磁盘的话需要先进行磁盘的转换. 解决办法: 先输入: D: 进行磁盘转换 然后cd到对应目录下即可:

  6. 一些windows下调试网络的命令行

    arp -a显示arp表, arp是IP到MAC的映射 arp -d清空arp表 ipconfig /displaydns 显示 ipconfig /flushdns 清空DNS缓存 route pr ...

  7. 在程序中调用命令行cmd接口

    nodeJS var cmd=require('node-cmd'); function check(p1,p2,callback){cmd.run('ShapeDescriptor.exe --in ...

  8. qt执行命令行失败_QT中QProcess调用命令行的痛苦经历

    在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在QT中通过QProcess类调用命令行的rar.exe来达到效果,但是没想到QProcess类用起来很麻烦,而且达不到效果,折腾了 ...

  9. QT中QProcess调用命令行的痛苦经历

    在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在QT中通过QProcess类调用命令行的rar.exe来达到效果,但是没想到QProcess类用起来很麻烦,而且达不到效果,折腾了 ...

最新文章

  1. 统计学习方法笔记(一)-k近邻算法原理及python实现
  2. 启明云端分享|AIOT+智慧屏解决方案,用色彩渲染智慧生活
  3. 聊聊我的高效学习法,让你快速拿下算法、MySQL…每天只花半小时
  4. 有序序列中的i个最大数(算法导论思考题9-1)
  5. 小米上市破发,其生态内部的隐患终于显露了?
  6. 2017年计算机基础知识答题宝典,最全全国计算机基础知识试题及答案考级宝典(2018)..pdf...
  7. java 正则 实例_Java正则表达式示例
  8. VC里的project panel窗口如何实现(转载)
  9. maven netty 配置_网络编程(二)Netty编程之一
  10. JAVA 面向对象的一些基础理解
  11. 庖丁解牛!深入剖析React Native下一代架构重构
  12. Logstash对nginx的access/error.log日志清洗并数据可视化监控设计
  13. 国税服务器反回文件错误,电子税务局常见问题解答电子税务局异常转办(一).pdf...
  14. windows10 安装两台mysql进行主从复制
  15. 船用炉灶的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  16. CF1428 G1,G2 . Lucky Numbers题解
  17. Arduino 8x8点阵怦然心动
  18. [TCP]基于TCP的心跳和加密设计
  19. c语言ascii码字符集共有多少个编码,标准ascii码字符集共有多少个编码
  20. xming Error: Can‘t open display:

热门文章

  1. 前端在线微信扫码支付的小功能
  2. macbook配置java环境变量_Mac系统中如何配置JDK环境变量?Mac中JDK环境变量配置教程...
  3. 错误一大堆,为什么机器翻译还有人用?
  4. Oracle 动态游标 PL/SQL 动态SQL语句 open for [using] 语句
  5. Failed to introspect Class druid问题
  6. Selenium+iframe准确定位元素
  7. 八月,愿你生活不拥挤,笑容不刻意
  8. CSS中子选择器和后代选择器之间有什么区别
  9. LaunchFaster 启动器工具 - 类似 Rolan 和音速启动的图标式快捷启动软件
  10. Lost connection to MySQL server during query的几种可能分析