我使用_popen启动进程来运行命令并收集输出
这是我的c ++代码:
bool exec(string &cmd, string &result)
{
result = "";
FILE* pipe = _popen(cmd.c_str(), "rt");
if (!pipe)
return(false);
char buffer[128];
while(!feof(pipe))
{
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return(true);
}
有没有办法在没有打开控制台窗口的情况下这样做(就像目前在_popen语句中那样)?
答案 0 :(得分:3)
在Windows上,具有STARTUPINFO结构的CreateProcess具有包含STARTF_USESSHOWWINDOW的dwFlags。然后将STARTUPINFO.dwFlags设置为SW_HIDE将导致触发时隐藏控制台窗口。示例代码(可能格式不正确,包含C ++和WinAPI的混合):
#include <windows.h>
#include <iostream>
#include <string>
using std::cout;
using std::endl;
void printError(DWORD);
int main()
{
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi = { 0 };
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
BOOL result = ::CreateProcessA("c:/windows/system32/notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if(result == 0) {
DWORD error = ::GetLastError();
printError(error);
std::string dummy;
std::getline(std::cin, dummy);
return error;
}
LPDWORD retval = new DWORD[1];
::GetExitCodeProcess(pi.hProcess, retval);
cout << "Retval: " << retval[0] << endl;
delete[] retval;
cout << "Press enter to continue..." << endl;
std::string dummy;
std::getline(std::cin, dummy);
return 0;
}
void printError(DWORD error) {
LPTSTR lpMsgBuf = nullptr;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
cout << reinterpret_cast<char*>(lpMsgBuf) << endl;
LocalFree(lpMsgBuf);
}
答案 1 :(得分:2)
据我所知,你不能 1 :你正在启动一个控制台应用程序(cmd.exe,它将运行指定的命令),Windows总是在启动时创建一个控制台窗口控制台应用程序。
CreateProcess
,则甚至隐藏它;问题是,_popen
没有传递这些标志,因此您必须使用Win32 API而不是_popen
来创建管道。答案 2 :(得分:0)
[最终编辑]
一个类似的SO问题合并了上面提到的所有内容,并为您提供输出 C++ popen command without console
[再次编辑]
ERK。抱歉,我对产卵过程感到兴奋。我重读你的q。除了额外的窗口,你实际上试图获取进程的stdout / stderr。我只想补充一点,为了这个目的,我的所有建议都令人遗憾地无关紧要。但我会把它们留在这里作为参考。
[被修改]
由于没有特殊原因(除了“open”适用于windows和mac),我使用ShellExecute产生进程而不是CreateProcess。我稍后会研究..但这是我的StartProcess函数。
隐藏或最小化似乎产生相同的结果。 cmd窗口确实产生了,但它被最小化,并且不会弹出桌面,这可能是您的主要目标。
#if defined(PLATFORM_WIN32)
#include <Windows.h>
#include <shellapi.h>
#elif defined(PLATFORM_OSX)
#include <sys/param.h>
#endif
namespace LGSysUtils
{
// -----------------------------------------------------------------------
// pWindow : {Optional} - can be NULL
// pOperation : "edit", "explore", "find", "open", "print"
// pFile : url, local file to execute
// pParameters : {Optional} - can be NULL otherwise a string of args to pass to pFile
// pDirectory : {Optional} - set cwd for process
// type : kProcessWinNormal, kProcessWinMinimized, kProcessWinMaximized, kProcessHidden
//
bool StartProcess(void* pWindow, const char* pOperation, const char* pFile, const char* pParameters, const char* pDirectory, LGSysUtils::eProcessWin type)
{
bool rc = false;
#if defined(PLATFORM_WIN32)
int showCmd;
switch(type)
{
case kProcessWinMaximized:
showCmd = SW_SHOWMAXIMIZED;
break;
case kProcessWinMinimized:
showCmd = SW_SHOWMINIMIZED;
break;
case kProcessHidden:
showCmd = SW_HIDE;
break;
case kProcessWinNormal:
default:
showCmd = SW_NORMAL;
}
int shellRC = (int)ShellExecute(reinterpret_cast<HWND>(pWindow), pOperation,pFile,pParameters,pDirectory,showCmd);
//Returns a value greater than 32 if successful, or an error value that is less than or equal to 32 otherwise.
if( shellRC > 32 )
{
rc = true;
}
#elif defined(PLATFORM_OSX)
char cmd[1024];
sprintf(cmd, "%s %s", pOperation, pFile);
int sysrc = system( cmd );
dbPrintf("sysrc = %d", sysrc);
rc = true;
#endif
return rc;
}
}
[和之前提到的]
如果您控制了已启动的应用程序的源代码,您可以尝试将其添加到main.cpp的顶部(或者您已命名的任何内容)
// make this process windowless/aka no console window
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
您也可以直接将这些选项提供给链接器。对于不同的构建配置,上面的内容更容易使用。