2012-04-04 5 views
6

estoy usando _popen para iniciar un proceso para ejecutar un comando y reunir la salida¿Hay alguna forma de detener _ abrir abriendo una ventana de dos?

Este es mi código 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); 
} 

¿Hay alguna manera de hacer esto sin una abertura de la ventana de DOS (como se actualmente lo hace en la declaración _popen)?

+0

¿Sigue apareciendo si redirige su salida a alguna parte?A otra tubería o un archivo? http://msdn.microsoft.com/en-us/library/ms682499.aspx (No sé, estoy simplemente especulando) –

Respuesta

2

Por lo que yo sé, no puede : está iniciando una aplicación de consola (cmd.exe, que ejecutará el comando especificado) y Windows siempre crea una ventana de consola al iniciar una aplicación de consola.


  1. aunque, usted puede ocultar la ventana después de que el proceso se inició, o incluso crear oculto si pasa las banderas apropiadas para CreateProcess; El problema es que _popen no pasa estos indicadores, por lo que debe usar las API de Win32 en lugar de _popen para crear su canalización.
+0

Estaba pensando que quizás podría ejecutar un proceso secundario ... ¿se puede hacer eso? y no mostrar una ventana? ¿También el uso de "sistema" también muestra una ventana? - Gracias –

+0

La única forma en que veo para ocultar la ventana es llamar directamente 'CreateProcess', especificando' SW_HIDE' en el miembro 'wShowWindow' de la estructura' STARTUPINFO'. –

3

En Windows, CreateProcess con una estructura STARTUPINFO que tiene dwFlags para incluir STARTF_USESSHOWWINDOW. Luego, al establecer STARTUPINFO.dwFlags en SW_HIDE, la ventana de la consola se ocultará cuando se active. Ejemplo de código (que tenga el formato correcto, y contiene una mezcla de C++ y API de Windows):

#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); 
} 
+0

Debería tenerse en cuenta a través de mi intento de edición (http://stackoverflow.com/review/suggested-edits/4113333) que no necesita llamar a new [] delete [] para retval. Sería mejor y más fácil de leer/mantener creando un DWORD retval = 0; y pasar :: GetExitCodeProcess (pi.hProcess, & retval); La línea de cout cambiaría también de retval [0] a retval. –

0

[Editar final]

un SO pregunta similar se funde todo lo dicho anteriormente y que lleva su salida C++ popen command without console

[Editado de nuevo]

erk. lo siento, me entusiasmé con los procesos de desove. Releí tu q. y aparte de la ventana adicional, en realidad está tratando de obtener el stdout/stderr del proceso. Solo me gustaría agregar que para ese propósito, todas mis sugerencias son tristemente irrelevantes. pero los dejaré aquí para referencia.

[Editado]

sin motivo específico (excepto que "abra" funciona para equipos Windows y Mac), utilizo ShellExecute para los procesos de desove en lugar de CreateProcess. Lo investigaré más tarde ... pero aquí está mi función StartProcess.

Ocultos o minimizados parecen producir el mismo resultado. la ventana de cmd aparece, pero se minimiza y nunca aparece en el escritorio, que podría ser su objetivo principal.

#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; 
} 

} 

[y anteriormente mencionado]

Si usted está en control del código fuente de la aplicación que se puso en marcha, podría intentar añadir esto a la parte superior de su main.cpp (o lo que usted tiene lo llamó)

// make this process windowless/aka no console window 
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") 

También podría alimentar esas opciones al vinculador directamente. Lo anterior es más fácil de jugar con diferentes configuraciones de construcción.

+2

No es tan fácil, ya que '_popen' siempre ejecuta' cmd.exe' para ejecutar el comando dado, y sobre las banderas del enlazador 'cmd.exe' no tiene control. –

+0

Gracias por la sugerencia, pero lamentablemente no tengo el control del código que se lanzó. –

Cuestiones relacionadas