C++获取外部exe程序的返回值,判断图片颜色模式

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
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容