写点什么

windows 下 C 与 C++ 执行 cmd 命令并实时获取输出

作者:DS小龙哥
  • 2022 年 3 月 25 日
  • 本文字数:2058 字

    阅读完需:约 7 分钟

1. 前言

在 windows 下一般会使用系统的 cmd 命令或者其他现成的一些命令行可执行程序来完成一些操作,比如:调用 ping 命令来测试网络是否畅通、调用 ffmpeg 命令进行视频转码等等。为了能在软件界面上有更好的交互输出,都需要将命令执行的过程拿到,进行处理,然后在界面上进行显示,让用户知道程序正在正常运行,下面就介绍几种输出的获取方式。


当前开发环境: win10 64 位 IDE-MSVC2017

2. 使用_popen 执行进程

通过_popen 打开进程进行执行,通过 fgets 获取进程的输出。


#include <stdio.h>#include <string.h>
int run_cmd(const char * cmd){ char MsgBuff[1024]; int MsgLen=1020; FILE * fp; if (cmd == NULL) { return -1; } if ((fp = _popen(cmd, "r")) == NULL) { return -2; } else { memset(MsgBuff, 0, MsgLen);
//读取命令执行过程中的输出 while (fgets(MsgBuff, MsgLen, fp) != NULL) { printf("MsgBuff: %s\n", MsgBuff); }
//关闭执行的进程 if(_pclose(fp) == -1) { return -3; } } return 0;}
int main(){ //const char *cmd = "ffmpeg -i D:\\123.mp4 -vf reverse D:\\out\\out1.mp4"; const char *cmd = "ping www.baidu.com"; int ret = 0; ret = run_cmd(cmd); printf("命令执行结果:%d\r\n",ret);
getchar(); return 0;}
复制代码


3. CreateProcess 重定向输出到文件

下面使用 CreateProcess 调用子进程运行,将输出保存在文件中,阻塞等待进程执行完毕。


int my_CreateProcess(){  SECURITY_ATTRIBUTES sa;  sa.nLength = sizeof(sa);  sa.lpSecurityDescriptor = NULL;  sa.bInheritHandle = TRUE;
_unlink("D:/out/output.log");
HANDLE h = CreateFile((L"D:/out/output.log"), FILE_APPEND_DATA, FILE_SHARE_WRITE | FILE_SHARE_READ, &sa, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
PROCESS_INFORMATION pi; STARTUPINFO si; BOOL ret = FALSE; DWORD flags = CREATE_NO_WINDOW;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = NULL; si.hStdError = h; si.hStdOutput = h;
TCHAR cmd[] = TEXT("ping www.baidu.com"); ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
if (ret) { WaitForSingleObject(pi.hProcess, INFINITE); printf("执行成功....\n"); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); //关闭文件 CloseHandle(h); return 0; } //关闭文件 CloseHandle(h); printf("执行失败....\n"); return -1;}
复制代码


4. CreateProcess 重定向输出到管道

为了能实时获取 CreateProcess 打开进程运行时实时输出的结果,可以将 CreateProcess 的输出重定向到管道文件,CreateProcess 将数据写到管道的写端,在父进程里再从管道的读端就能实时读取数据。


int my_CreateProcess(){  BOOL run_pipe;
PROCESS_INFORMATION pi; STARTUPINFO si; BOOL ret = FALSE; DWORD flags = CREATE_NO_WINDOW;
_unlink("D:/out/output.log");
char pBuffer[210]; SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; HANDLE hReadPipe, hWritePipe; run_pipe=CreatePipe(&hReadPipe, &hWritePipe, &sa, 0); printf("run_pipe=%d\n", run_pipe);
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = NULL; si.hStdError = hWritePipe; si.hStdOutput = hWritePipe;
TCHAR cmd[] = TEXT("ffmpeg -i D:\\123.mp4 -vf reverse D:\\out\\out1.mp4");
ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi);
if (ret) { while (true) { DWORD ExitCode = 0; //判断进程是否执行结束 GetExitCodeProcess(pi.hProcess, &ExitCode); if (ExitCode == STILL_ACTIVE) //正在运行 { DWORD RSize=0; BOOL run_s=0; run_s =ReadFile(hReadPipe, pBuffer,200,&RSize,NULL); pBuffer[RSize] = '\0'; printf("返回结果:%d,%d,%s\n", run_s, RSize, pBuffer); } else //结束 { printf("执行完毕...\n"); break; } } //WaitForSingleObject(pi.hProcess, INFINITE); printf("执行成功....\n"); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return 0; } printf("执行失败....\n"); return -1;}
复制代码


发布于: 刚刚阅读数: 2
用户头像

DS小龙哥

关注

之所以觉得累,是因为说的比做的多。 2022.01.06 加入

熟悉C/C++、51单片机、STM32、Linux应用开发、Linux驱动开发、音视频开发、QT开发. 目前已经完成的项目涉及音视频、物联网、智能家居、工业控制领域

评论

发布
暂无评论
windows下C与C++执行cmd命令并实时获取输出_3月月更_DS小龙哥_InfoQ写作平台