C++获取外部exe程序的返回值
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR *argv[])
{
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(STARTUPINFOA);
TCHAR cmd[256] = _T("D:7za.exe a D:nv1.zip D:test*.*");
BOOL working = ::CreateProcess(NULL, cmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS , NULL, NULL, &si, &pi);
if (working == 0)
{
DWORD error = GetLastError();
cout << "CreateProcess Error : " << error << endl;
getchar();
return 0;
}
WaitForSingleObject(pi.hProcess, INFINITE);
unsigned long Result;
GetExitCodeProcess(pi.hProcess, &Result);
cout << "Exit Code : " << Result << endl;
getchar();
return 0;
}
调用命令行程序并获取返回信息
CString ExeCmd(CString pszCmd)
{
//创建匿名管道
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
HANDLE hRead, hWrite;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
{
return _T("");
}
//设置命令行进程启动信息(以隐藏方式启动命令并定位其输出到hWrite)
STARTUPINFO si = {sizeof(STARTUPINFO)};
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdError = hWrite;
si.hStdOutput = hWrite;
//启动命令行
PROCESS_INFORMATION pi;
if (!CreateProcess(NULL, (LPWSTR)(LPCWSTR)pszCmd, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi))
{
return _T("");
}
//立即关闭hWrite
CloseHandle(hWrite);
//读取命令行返回值
char buff[1024] = {0};
DWORD dwRead = 0;
while (ReadFile(hRead, buff, 1024, &dwRead, NULL))
{
}
CString strRet(buff);
CloseHandle(hRead);
return strRet;
}
使用:
ExeCmd(_T("ping baidu.com"));
ExeCmd(_T("identify -format "%[colorspace]" E:P70306-163226.jpg"));
其他参考:
BOOL Start(LPCTSTR lpszTaskInfo)
{
if (!lpszTaskInfo)
{
return FALSE;
}
if (m_hRenderProcess)
{
if (Wait(0))
{
m_nProgress = 0;
SAFE_CLOSE_HANDLE(m_hRenderProcess);
m_dwRenderThreadId = 0;
}
else
{
return FALSE;
}
}
BOOL bRet = FALSE;
HANDLE hDebugInfo = NULL;
do
{
TCHAR szDebugLog[MAX_PATH];
_tcscpy(szDebugLog, m_szFastRenderExPath);
_tcscat(szDebugLog, _T(".debug"));
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
hDebugInfo = CreateFile(szDebugLog, FILE_WRITE_DATA, FILE_SHARE_READ, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdInput = NULL;
si.hStdOutput = hDebugInfo;
si.hStdError = hDebugInfo;
si.wShowWindow = SW_HIDE;
TCHAR szCmdline[MAX_PATH * 2];
_sntprintf(szCmdline, ARRAYSIZE(szCmdline), _T(" -i "%s""), lpszTaskInfo); // 第一个空格非常重要
// Start the child process.
if( !CreateProcess( m_szFastRenderExPath, // Module name
szCmdline, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
TRUE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
break;
}
// Close process and thread handles.
m_hRenderProcess = pi.hProcess;
CloseHandle( pi.hThread );
m_dwRenderThreadId = pi.dwThreadId;
// Start the message receive thread
if (!m_dwReceiveThreadId)
{
HANDLE hThread = (HANDLE) _beginthreadex(NULL, 0, ThreadFn, this, 0, &m_dwReceiveThreadId);
if (hThread == NULL)
{
break;
}
CloseHandle(hThread);
}
if (!m_hMsgEvent)
{
m_hMsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
}
else
{
ResetEvent(m_hMsgEvent);
}
bRet = TRUE;
}
while (FALSE);
SAFE_CLOSE_HANDLE(hDebugInfo);
if (!bRet)
{
if (m_hRenderProcess)
{
TerminateProcess(m_hRenderProcess, -1);
SAFE_CLOSE_HANDLE(m_hRenderProcess);
}
m_dwRenderThreadId = 0;
SAFE_CLOSE_HANDLE(m_hMsgEvent);
}
return bRet;
}
C++调用外部程序
三个SDK函数: WinExec, ShellExecute,CreateProcess
ShellExecute
void mySystem(CString cmd, CString par, int nShow)
{
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = cmd;//调用的程序名
ShExecInfo.lpParameters = par;//调用程序的命令行参数
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;//窗口状态为隐藏
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo); //启动新的程序
WaitForSingleObject(ShExecInfo.hProcess,INFINITE);////等到该进程结束
}
SHELLEXECUTEINFO execteInfo;
execteInfo.cbSize = sizeof(SHELLEXECUTEINFO);
execteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
execteInfo.hwnd = nullptr;
execteInfo.lpVerb = L"open";
execteInfo.lpFile = wstrLoginExe.c_str();
execteInfo.lpParameters = L"";
execteInfo.lpDirectory = nullptr;
execteInfo.nShow = SW_SHOW;
execteInfo.hInstApp = nullptr;
execteInfo.lpIDList = nullptr;
execteInfo.lpClass = nullptr;
execteInfo.hkeyClass = nullptr;
execteInfo.dwHotKey = 0;
execteInfo.hMonitor = nullptr;
execteInfo.hIcon = nullptr;
execteInfo.hProcess = nullptr;
if (ShellExecuteEx(&execteInfo))
{
if (execteInfo.hProcess)
{
WaitForSingleObject(execteInfo.hProcess, INFINITE);
::CloseHandle(execteInfo.hProcess);
}
}
bool CApp::CTest(const std::wstring &wstrExe)
{
SHELLEXECUTEINFO execteInfo;
execteInfo.cbSize = sizeof(SHELLEXECUTEINFO);
execteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
execteInfo.hwnd = nullptr;
execteInfo.lpVerb = L"open";
execteInfo.lpFile = wstrExe.c_str();
execteInfo.lpParameters = L"";
execteInfo.lpDirectory = nullptr;
execteInfo.nShow = SW_SHOW;
execteInfo.hInstApp = nullptr;
execteInfo.lpIDList = nullptr;
execteInfo.lpClass = nullptr;
execteInfo.hkeyClass = nullptr;
execteInfo.dwHotKey = 0;
execteInfo.hMonitor = nullptr;
execteInfo.hIcon = nullptr;
execteInfo.hProcess = nullptr;
if (ShellExecuteEx(&execteInfo))
{
if (execteInfo.hProcess)
{
WaitForSingleObject(execteInfo.hProcess, INFINITE);
::CloseHandle(execteInfo.hProcess);
}
wchar_t lpszDefaultDir[MAX_PATH] = { 0 };
wchar_t wszINIFilePathName[MAX_PATH] = { 0 };
memset(lpszDefaultDir, 0, MAX_PATH * sizeof(wchar_t));
memset(wszINIFilePathName, 0, MAX_PATH * sizeof(wchar_t));
LPITEMIDLIST pidll = NULL;
::SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidll);
if (pidll && ::SHGetPathFromIDList(pidll, wszINIFilePathName))
{
::GetShortPathName(wszINIFilePathName, lpszDefaultDir, _MAX_PATH);
}
}
return true;
}
lpVerb还支持runas,启动管理员权限程序
CreateProcess
PROCESS_INFORMATION pi;
DWORD dwExitCode;
//Spawn the child process.
BOOL fSuccess = CreateProcess(..., ...);
if(fSuccess)
{
//Close the thread handle as soon as
//it is no longer needed!
CloseHandle(pi.hThread);
//Suspend our execution until
//the child has terminated.
WaitForSingleObject(pi.hProcess, INFINITE);
//The child process terminated;
//get its exit code.
GetExitCodeProcess(pi.hProcess,
&dwExitCode);
//Close the process handle as soon as
//it is no longer needed.
CloseHandle(pi.hProcess);
}
TCHAR szCommandLine[] = TEXT(".ffplay.exe -window_title CDFacePlay -exitonkeydown -exitonmousedown -fs -autoexit .video.mp4");
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
si.wShowWindow = FALSE;
si.dwFlags = STARTF_USESHOWWINDOW;
BOOL ret = ::CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (ret)
{
WaitForSingleObject(pi.hProcess, INFINITE);//等待进程完成
}
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CreateProcess
https://baike.baidu.com/item/CreateProcess
//传形参时应该这样传参 cmd.exe /c type 1.txt>2.txt
#include <iostream>
#include <string>
//#pragma comment( linker, "/subsystem:"windows" /entry:"mainCRTStartup"" )//隐藏命令行
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
using namespace std;
wstring Str2Wstr(string str)
{
unsigned len = str.size() * 2;// 预留字节数
setlocale(LC_CTYPE, ""); //必须调用此函数
wchar_t *p = new wchar_t[len];// 申请一段内存存放转换后的字符串
mbstowcs(p, str.c_str(), len);// 转换
std::wstring str1(p);
delete[] p;// 释放申请的内存
return str1;
}
string ExeCmd(string pszCmd)
{
wstring pszCmd_w = Str2Wstr(pszCmd);
wcout << "pszCmd_w is " << pszCmd_w << endl;
// 创建匿名管道,write->read;
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
HANDLE hRead, hWrite;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
{
cout << "@ CreatePipe failed!" << endl;
return (" ");
}
cout << "@0" << endl;
// 设置命令行进程启动信息(以隐藏方式启动命令并定位其输出到hWrite
STARTUPINFO si = { sizeof(STARTUPINFO) }; // Pointer to STARTUPINFO structure;
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
//si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; //隐藏窗口;
si.hStdError = hWrite;
si.hStdError = hWrite;
si.hStdOutput = hWrite; //管道的输入端口连接命令行的输出;
// 启动命令行
PROCESS_INFORMATION pi;// Pointer to PROCESS_INFORMATION structure;
if (!CreateProcess(NULL,
(LPWSTR)pszCmd_w.c_str(),
NULL,
NULL,
TRUE,
//FALSE, // Set handle inheritance to FALSE
NULL,
//0, // No creation flags
NULL,
NULL,
&si,
&pi))
{
cout << "@ CreateProcess failed!" << endl;
return ("Cannot create process");
}
CloseHandle(hWrite);//关闭管道的输入端口;
// 读取命令行返回值
string strRetTmp;
char buff[1024] = { 0 };
DWORD dwRead = 0;
strRetTmp = buff;
while (ReadFile(hRead, buff, 1024, &dwRead, NULL))//从管道的输出端获取命令行写入的数据;
{
cout << "buff = " << buff << endl;
strRetTmp += buff;
}
CloseHandle(hRead);//关闭管道的输出端口;
cout << "strRetTmp:"<<strRetTmp << endl;
return strRetTmp;
}
封装类
/* ====================================================
* Copyright: 275659704@qq.com
* Author: wfy
* Date: 2018-4-15
* Description: 提供CreateProcess()执行
* 命令并通过匿名管道获取的封装
==================================================== */
#ifndef __CMD_HANDLER_H__
#define __CMD_HANDLER_H__
#include <Windows.h>
/* buffer的最大长度 */
#define PIPE_BUFFER_SIZE 1024
/* 命令参数 */
typedef struct _CHCmdParam CHCmdParam;
struct _CHCmdParam
{
/* 初始化为 sizeof(CommandParam) */
int iSize;
/* 外部命令,不需要用则设置为-1, 提供给外部使用
*/
int iCommand;
/* 超时时间,单位秒 */
int iTimeOut;
/* 命令行要执行的命令 */
TCHAR szCommand[MAX_PATH];
/* 用户数据 */
void* pUserData;
/* 命令执行后的回调 */
void (*OnCmdEvent)(const CHCmdParam* pParam, HRESULT hResultCode, char* szResult);
};
class CCmdHandler
{
private:
BOOL m_bInit;
STARTUPINFO m_startupInfo;
PROCESS_INFORMATION m_processInfo;
SECURITY_ATTRIBUTES m_saOutPipe;
DWORD m_dwErrorCode;
HANDLE m_hPipeRead;
HANDLE m_hPipeWrite;
CHCmdParam m_CommandParam;
TCHAR m_szReadBuffer[PIPE_BUFFER_SIZE];
TCHAR m_szWriteBuffer[PIPE_BUFFER_SIZE];
char m_szPipeOut[PIPE_BUFFER_SIZE];
HRESULT ExecuteCmdWait();
public:
CCmdHandler();
~CCmdHandler();
/*
* 初始化接口,调用其余接口之前调用
* 成功返回S_OK
*/
HRESULT Initalize();
/*
* 结束接口
*/
HRESULT Finish();
/*
* 执行命令接口,接口调用成功返回S_OK
* param[in] pCommmandParam: 指向一个CHCmdParam命令参数结构的指针
*/
HRESULT HandleCommand(CHCmdParam* pCommmandParam);
/*
* 返回错误码,便于差距接口调用失败后产生什么错误
*/
DWORD GetErrorCode() { return m_dwErrorCode; }
};
#endif // !__CMD_HANDLER_H__
#include "CmdHandler.h"
#include <tchar.h>
#define EXCEPTIION_STATE_CHECK
if (!m_bInit) return E_NOTIMPL
CCmdHandler::CCmdHandler()
: m_bInit(FALSE)
, m_dwErrorCode(0)
, m_hPipeRead(NULL)
, m_hPipeWrite(NULL)
{
ZeroMemory(m_szReadBuffer, sizeof(m_szReadBuffer));
ZeroMemory(m_szWriteBuffer, sizeof(m_szWriteBuffer));
ZeroMemory(&m_CommandParam, sizeof(m_CommandParam));
}
CCmdHandler::~CCmdHandler()
{
}
HRESULT CCmdHandler::Initalize()
{
// 初始化,创建匿名管道
if (m_bInit) return S_OK;
m_bInit = TRUE;
ZeroMemory(m_szReadBuffer, sizeof(m_szReadBuffer));
ZeroMemory(&m_saOutPipe, sizeof(m_saOutPipe));
m_saOutPipe.nLength = sizeof(SECURITY_ATTRIBUTES);
m_saOutPipe.lpSecurityDescriptor = NULL;
m_saOutPipe.bInheritHandle = TRUE;
ZeroMemory(&m_startupInfo, sizeof(STARTUPINFO));
ZeroMemory(&m_processInfo, sizeof(PROCESS_INFORMATION));
if (!CreatePipe(&m_hPipeRead, &m_hPipeWrite, &m_saOutPipe, PIPE_BUFFER_SIZE))
{
m_dwErrorCode = GetLastError();
return E_FAIL;
}
return S_OK;
}
HRESULT CCmdHandler::Finish()
{
EXCEPTIION_STATE_CHECK;
if (m_hPipeRead)
{
CloseHandle(m_hPipeRead);
m_hPipeRead = NULL;
}
if (m_hPipeWrite)
{
CloseHandle(m_hPipeWrite);
m_hPipeWrite = NULL;
}
return S_OK;
}
HRESULT CCmdHandler::HandleCommand(CHCmdParam* pCommmandParam)
{
EXCEPTIION_STATE_CHECK;
if (!pCommmandParam || pCommmandParam->iSize != sizeof(CHCmdParam))
return E_INVALIDARG;
if (_tcslen(pCommmandParam->szCommand) <= 0)
return E_UNEXPECTED;
memset(&m_CommandParam, 0, sizeof(m_CommandParam));
m_CommandParam = *pCommmandParam;
return ExecuteCmdWait();
}
HRESULT CCmdHandler::ExecuteCmdWait()
{
EXCEPTIION_STATE_CHECK;
HRESULT hResult = E_FAIL;
DWORD dwReadLen = 0;
DWORD dwStdLen = 0;
m_startupInfo.cb = sizeof(STARTUPINFO);
m_startupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
m_startupInfo.hStdOutput = m_hPipeWrite;
m_startupInfo.hStdError = m_hPipeWrite;
m_startupInfo.wShowWindow = SW_HIDE;
DWORD dTimeOut = m_CommandParam.iTimeOut >= 3000 ? m_CommandParam.iTimeOut : 5000;
do
{
if (!CreateProcess(NULL, m_CommandParam.szCommand,
NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL,
&m_startupInfo, &m_processInfo))
{
m_dwErrorCode = GetLastError();
hResult = E_FAIL;
break;
}
if (WAIT_TIMEOUT == WaitForSingleObject(m_processInfo.hProcess, dTimeOut))
{
m_dwErrorCode = GetLastError();
hResult = CO_E_SERVER_START_TIMEOUT;
if (m_CommandParam.OnCmdEvent)
m_CommandParam.OnCmdEvent(&m_CommandParam, CO_E_SERVER_START_TIMEOUT, "");
break;
}
// 预览管道中数据的内容
if (!PeekNamedPipe(m_hPipeRead, NULL, 0, NULL, &dwReadLen, NULL)
|| dwReadLen <= 0)
{
m_dwErrorCode = GetLastError();
hResult = E_FAIL;
break;
}
else
{
ZeroMemory(m_szPipeOut, sizeof(m_szPipeOut));
// 读取管道中的数据
if (ReadFile(m_hPipeRead, m_szPipeOut, dwReadLen, &dwStdLen, NULL))
{
hResult = S_OK;
if (m_CommandParam.OnCmdEvent)
m_CommandParam.OnCmdEvent(&m_CommandParam, S_OK, m_szPipeOut);
break;
}
else
{
m_dwErrorCode = GetLastError();
break;
}
}
} while (0);
if (m_processInfo.hThread)
{
CloseHandle(m_processInfo.hThread);
m_processInfo.hThread = NULL;
}
if (m_processInfo.hProcess)
{
CloseHandle(m_processInfo.hProcess);
m_processInfo.hProcess = NULL;
}
return hResult;
}
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <string>
#include "CmdHandler.h"
#define SYSTEM_PAUSE system("pause")
void OnCommandEvent(const CHCmdParam* pParam, HRESULT hResultCode, char* szResult);
int main(int argc, TCHAR** argv)
{
CHCmdParam cmdParam;
CCmdHandler cmdHandler;
HRESULT cmdResult = S_OK;
ZeroMemory(&cmdParam, sizeof(cmdParam));
cmdParam.iSize = sizeof(CHCmdParam);
// 这里测试F磁盘Test目录下,命令格式为 cmd.exe /C + 命令
TCHAR* szCmd = _T("cmd.exe /C dir F:Test&& echo S_OK || echo E_FAIL");
_tcscpy_s(cmdParam.szCommand, szCmd);
cmdParam.OnCmdEvent = OnCommandEvent;
cmdParam.iTimeOut = 3000;
cmdResult = cmdHandler.Initalize();
if (cmdResult != S_OK)
{
printf("cmd handler 初始化失败
");
SYSTEM_PAUSE;
return 0;
}
cmdResult = cmdHandler.HandleCommand(&cmdParam);
if (cmdResult != S_OK)
{
printf("cmd handler 执行命令接口调用失败
");
cmdHandler.Finish();
SYSTEM_PAUSE;
return 0;
}
system("pause");
return 0;
}
void OnCommandEvent(const CHCmdParam* pParam, HRESULT hResultCode, char* szResult)
{
if (!szResult || !szResult[0]) return;
if (!pParam || hResultCode != S_OK) return;
printf("============== 回调 ==============
");
std::string echo_data(szResult);
std::string s_ok("S_OK");
std::string::size_type pos = echo_data.find(s_ok);
if (pos != std::string::npos)
printf("命令执行成功
");
else
printf("命令执行失败
");
printf("执行返回的结构:
");
printf("========================================
");
printf("%s
", szResult);
}
其他相关
在Visual C++里基本上有四种方法执行命令:
system(), _wsystem()
ShellExecute() or ShellExecuteEx()
CreateProcess()
WinExec() //这个函数只适用于16位windows系统。
参考:
C++获取外部exe程序的返回值 调用命令行程序并获取返回信息ImageMagick–identify详解
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END















暂无评论内容