vfp sintaxis parametros ejemplos visual-c++ shellexecute

visual-c++ - sintaxis - shellexecute vba



¿Cómo esperar a que ShellExecute se ejecute? (2)

Logré usar ShellExecute en VC ++ para lanzar un documento. Ahora deseo ejecutar una herramienta de línea de comandos que recibe algunos argumentos, y ejecutarla en segundo plano (como oculta, no minimizada) y dejar que bloquee el flujo de mi programa, de modo que pueda esperar a que termine. Cómo alterar la línea de comandos de:

ShellExecute(NULL,"open",FULL_PATH_TO_CMD_LINE_TOOL,ARGUMENTS,NULL,SW_HIDE);

El problema es que tengo una herramienta que convierte html a pdf, y deseo que una vez que la herramienta haya terminado, también conocido como pdf, tenga otro ShellExecute para verlo.


Hay un artículo de CodeProject que muestra cómo, usando ShellExecuteEx lugar de ShellExecute :

SHELLEXECUTEINFO ShExecInfo = {0}; ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShExecInfo.hwnd = NULL; ShExecInfo.lpVerb = NULL; ShExecInfo.lpFile = "c://MyProgram.exe"; ShExecInfo.lpParameters = ""; ShExecInfo.lpDirectory = NULL; ShExecInfo.nShow = SW_SHOW; ShExecInfo.hInstApp = NULL; ShellExecuteEx(&ShExecInfo); WaitForSingleObject(ShExecInfo.hProcess, INFINITE); CloseHandle(ShExecInfo.hProcess);

El punto crucial es la bandera SEE_MASK_NOCLOSEPROCESS , que, como dice MSDN

Se usa para indicar que el miembro hProcess recibe el identificador de proceso. Este identificador se usa normalmente para permitir que una aplicación descubra cuándo finaliza un proceso creado con ShellExecuteEx

Además, tenga en cuenta que:

La aplicación que realiza la llamada es responsable de cerrar el identificador cuando ya no se necesita.


También puede usar CreateProcess en lugar de ShellExecute / ShellExecuteEx. Esta función incluye una opción de contenedor cmd.exe, que devuelve el código de salida y devuelve stdout. (Los incluidos pueden no ser perfectos).

Notas: En mi uso, sabía que tenía que haber resultados stdout, pero la función PeekedNamePipe no siempre devolvería el recuento de bytes en el primer intento, por lo tanto, el bucle allí. Tal vez, alguien puede resolver esto y publicar una revisión? Además, ¿tal vez debería producirse una versión alternativa que devuelva stderr por separado?

#include <stdio.h> #include <iostream> #include <fstream> #include <sstream> #include <Shellapi.h> /* Note: The exitCode for a "Cmd Process" is not the exitCode for a sub process launched from it! That can be retrieved via the errorlevel variable in the command line like so: set errorlevel=&[launch command]&echo.&echo exitCode=%errorlevel%&echo. The stdOut vector will then contain the exitCode on a seperate line */ BOOL executeCommandLine( const CStringW &command, DWORD &exitCode, const BOOL asCmdProcess=FALSE, std::vector<CStringW> *stdOutLines=NULL ) { // Init return values BOOL bSuccess = FALSE; exitCode = 0; if( stdOutLines ) stdOutLines->clear(); // Optionally prepend cmd.exe to command line to execute CStringW cmdLine( (asCmdProcess ? L"cmd.exe /C " : L"" ) + command ); // Create a pipe for the redirection of the STDOUT // of a child process. HANDLE g_hChildStd_OUT_Rd = NULL; HANDLE g_hChildStd_OUT_Wr = NULL; SECURITY_ATTRIBUTES saAttr; saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); saAttr.bInheritHandle = TRUE; saAttr.lpSecurityDescriptor = NULL; bSuccess = CreatePipe( &g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0); if( !bSuccess ) return bSuccess; bSuccess = SetHandleInformation( g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0 ); if( !bSuccess ) return bSuccess; // Setup the child process to use the STDOUT redirection PROCESS_INFORMATION piProcInfo; STARTUPINFO siStartInfo; ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) ); ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) ); siStartInfo.cb = sizeof(STARTUPINFO); siStartInfo.hStdError = g_hChildStd_OUT_Wr; siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; siStartInfo.dwFlags |= STARTF_USESTDHANDLES; // Execute a synchronous child process & get exit code bSuccess = CreateProcess( NULL, cmdLine.GetBuffer(), // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited 0, // creation flags NULL, // use parent''s environment NULL, // use parent''s current directory &siStartInfo, // STARTUPINFO pointer &piProcInfo ); // receives PROCESS_INFORMATION if( !bSuccess ) return bSuccess; WaitForSingleObject( piProcInfo.hProcess, (DWORD)(-1L) ); GetExitCodeProcess( piProcInfo.hProcess, &exitCode ); CloseHandle( piProcInfo.hProcess ); CloseHandle( piProcInfo.hThread ); // Return if the caller is not requesting the stdout results if( !stdOutLines ) return TRUE; // Read the data written to the pipe DWORD bytesInPipe = 0; while( bytesInPipe==0 ){ bSuccess = PeekNamedPipe( g_hChildStd_OUT_Rd, NULL, 0, NULL, &bytesInPipe, NULL ); if( !bSuccess ) return bSuccess; } if( bytesInPipe == 0 ) return TRUE; DWORD dwRead; CHAR *pipeContents = new CHAR[ bytesInPipe ]; bSuccess = ReadFile( g_hChildStd_OUT_Rd, pipeContents, bytesInPipe, &dwRead, NULL); if( !bSuccess || dwRead == 0 ) return FALSE; // Split the data into lines and add them to the return vector std::stringstream stream( pipeContents ); std::string str; while( getline( stream, str ) ) stdOutLines->push_back( CStringW( str.c_str() ) ); return TRUE; }