Есть ли способ остановить popen, открывающий окно dos?
Я использую _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)?
3 ответов
насколько я знаю, вы не можете1: вы запускаете консольное приложение (cmd.exe, который будет запускать указанную команду), а Windows всегда создает окно консоли при запуске консольного приложения.
- хотя, вы can скрыть окно после запуска процесса или даже создать его скрытым, если вы передаете соответствующие флаги
CreateProcess
; проблема в том,_popen
Не передавайте эти флаги, поэтому вам нужно использовать API Win32 из_popen
для создания трубы.
в Windows CreateProcess со структурой STARTUPINFO, которая имеет dwFlags для включения STARTF_USESSHOWWINDOW. Потом 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);
}
[Окончательное Редактирование]
аналогичный вопрос so объединяет все сказанное выше и получает ваш вывод команда c++ popen без консоли
[снова]
erk. извини, что так разволновался из-за процесса нереста. Я перечитал ваш вопрос. и помимо дополнительного окна вы фактически пытаетесь получить stdout/stderr процессов. Я просто хотел бы добавить, что для этой цели все мои предложения, к сожалению, неуместны. но я оставлю их здесь ссылка.
[отредактировано]
без особых причин (за исключением того, что "open" работает как для windows, так и для Mac), я использую ShellExecute для процессов нереста, а не CreateProcess. Я выясню это позже..но вот моя функция StartProcess.
Hidden или Minimized, похоже, дают тот же результат. окно 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;
}
}
[и упоминалось ранее]
Если вы контролируете исходный код для запущенного приложения,вы можете попробовать добавить его в начало своего основного.cpp (или как вы его назвали)
// make this process windowless/aka no console window
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
вы также можете напрямую передать эти параметры компоновщику. Вышесказанное проще играть с различными конфигурациями сборки imho.