From fbf456aa8952c6d2d3edeea1208b0e3159a3cb8d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 23 Mar 2002 01:22:17 +0000 Subject: [PATCH] added wxEXEC_NOHIDE flag, modified wxExecute() to take a combination of bit flags instead of a boolean parameter git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14738 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/function.tex | 34 +++++++++++++++++++++------ include/wx/utils.h | 26 +++++++++++++++++---- src/msw/utilsexc.cpp | 47 +++++++++++++++++++++++--------------- src/unix/utilsunx.cpp | 18 ++++++++------- 4 files changed, 86 insertions(+), 39 deletions(-) diff --git a/docs/latex/wx/function.tex b/docs/latex/wx/function.tex index cfaa54463a..9fe55f3bf6 100644 --- a/docs/latex/wx/function.tex +++ b/docs/latex/wx/function.tex @@ -424,9 +424,9 @@ processes. \membersection{::wxExecute}\label{wxexecute} -\func{long}{wxExecute}{\param{const wxString\& }{command}, \param{bool }{sync = FALSE}, \param{wxProcess *}{callback = NULL}} +\func{long}{wxExecute}{\param{const wxString\& }{command}, \param{int }{sync = wxEXEC\_ASYNC}, \param{wxProcess *}{callback = NULL}} -\func{long}{wxExecute}{\param{char **}{argv}, \param{bool }{sync = FALSE}, \param{wxProcess *}{callback = NULL}} +\func{long}{wxExecute}{\param{char **}{argv}, \param{int }{flags = wxEXEC\_ASYNC}, \param{wxProcess *}{callback = NULL}} \func{long}{wxExecute}{\param{const wxString\& }{command}, \param{wxArrayString\& }{output}} @@ -450,8 +450,9 @@ arguments, terminated by NULL. The semantics of the third and fourth versions is different from the first two and is described in more details below. -If {\it sync} is FALSE (the default), flow of control immediately returns. -If TRUE, the current application waits until the other program has terminated. +If {\it flags} parameter contains {\tt wxEXEC\_ASYNC} flag (the default), flow +of control immediately returns. If it contains {\tt wxEXEC\_SYNC}, the current +application waits until the other program has terminated. In the case of synchronous execution, the return value is the exit code of the process (which terminates by the moment the function returns) and will be @@ -469,10 +470,15 @@ case of using DDE under Windows for command execution). In particular, in this, and only this, case the calling code will not get the notification about process termination. -If callback isn't NULL and if execution is asynchronous (note that callback -parameter can not be non-NULL for synchronous execution), +If callback isn't NULL and if execution is asynchronous, \helpref{wxProcess::OnTerminate}{wxprocessonterminate} will be called when -the process finishes. +the process finishes. Specifying this parameter also allows you to redirect the +standard input and/or output of the process being launched by calling +\helpref{Redirect}{wxprocessredirect}. If the child process IO is redirected, +under Windows the process window is not shown by default (this avoids having to +flush an unnecessary console for the processes which don't create any windows +anyhow) but a {\tt wxEXEC\_NOHIDE} flag can be used to prevent this from +happening, i.e. with this flag the child process window will be shown normally. Finally, you may use the third overloaded version of this function to execute a process (always synchronously) and capture its output in the array @@ -482,6 +488,20 @@ the messages from standard error output in the {\it errors} array. See also \helpref{wxShell}{wxshell}, \helpref{wxProcess}{wxprocess}, \helpref{Exec sample}{sampleexec}. +\wxheading{Parameters} + +\docparam{command}{The command to execute and any parameters to pass to it as a +single string.} + +\docparam{argv}{The command to execute should be the first element of this +array, any additional ones are the command parameters and the array must be +terminated with a NULL pointer.} + +\docparam{flags}{Combination of bit masks {\tt wxEXEC\_ASYNC}, +{\tt wxEXEC\_SYNC} and {\tt wxEXEC\_NOHIDE}} + +\docparam{callback}{An optional pointer to \helpref{wxProcess}{wxprocess}} + \wxheading{Include files} diff --git a/include/wx/utils.h b/include/wx/utils.h index 854711fa9a..2306a14cd3 100644 --- a/include/wx/utils.h +++ b/include/wx/utils.h @@ -148,17 +148,33 @@ WXDLLEXPORT wxString wxDecToHex(int dec); // Process management // ---------------------------------------------------------------------------- -// Execute another program. Returns 0 if there was an error, a PID otherwise. -WXDLLEXPORT long wxExecute(wxChar **argv, bool sync = FALSE, +// NB: for backwars compatibility reasons the values of wxEXEC_[A]SYNC *must* +// be 0 and 1, don't change! + +enum +{ + wxEXEC_ASYNC = 0, // execute the process asynchronously + wxEXEC_SYNC = 1, // synchronously + wxEXEC_NOHIDE = 2 // under Windows, don't hide the child even if it's + // IO is redirected (this is done by default) +}; + +// Execute another program. +// +// If flags contain wxEXEC_SYNC, return -1 on failure and the exit code of the +// process if everything was ok. Otherwise (i.e. if wxEXEC_ASYNC), return 0 on +// failure and the PID of the launched process if ok. +WXDLLEXPORT long wxExecute(wxChar **argv, int flags = wxEXEC_ASYNC, wxProcess *process = (wxProcess *) NULL); -WXDLLEXPORT long wxExecute(const wxString& command, bool sync = FALSE, +WXDLLEXPORT long wxExecute(const wxString& command, int flags = wxEXEC_ASYNC, wxProcess *process = (wxProcess *) NULL); -// execute the command capturing its output into an array line by line +// execute the command capturing its output into an array line by line, this is +// always synchronous WXDLLEXPORT long wxExecute(const wxString& command, wxArrayString& output); -// also capture stderr +// also capture stderr (also synchronous) WXDLLEXPORT long wxExecute(const wxString& command, wxArrayString& output, wxArrayString& error); diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index 8fcae76c3c..db09033338 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -360,7 +360,7 @@ static bool wxExecuteDDE(const wxString& ddeServer, #endif // wxUSE_IPC -long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) +long wxExecute(const wxString& cmd, int flags, wxProcess *handler) { wxCHECK_MSG( !!cmd, 0, wxT("empty command in wxExecute") ); @@ -439,7 +439,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) // termination, try to execute DDE command right now, it can succeed if // the process is already running - but as it fails if it's not // running, suppress any errors it might generate - if ( !sync ) + if ( !(flags & wxEXEC_SYNC) ) { wxLogNull noErrors; if ( wxExecuteDDE(ddeServer, ddeTopic, ddeCommand) ) @@ -484,8 +484,9 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) { wxLogSysError(_("Can't create the inter-process read pipe")); - // indicate failure in both cases - return sync ? -1 : 0; + // indicate failure: we need to return different error code + // depending on the sync flag + return flags & wxEXEC_SYNC ? -1 : 0; } // and a stdout one @@ -496,7 +497,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) wxLogSysError(_("Can't create the inter-process write pipe")); - return sync ? -1 : 0; + return flags & wxEXEC_SYNC ? -1 : 0; } (void)::CreatePipe(&hpipeStderr[0], &hpipeStderr[1], &security, 0); @@ -513,15 +514,20 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) #if wxUSE_STREAMS if ( redirect ) { - // when the std IO is redirected, we don't show the (console) process - // window - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.dwFlags = STARTF_USESTDHANDLES; si.hStdInput = hpipeStdin[0]; si.hStdOutput = hpipeStdout[1]; si.hStdError = hpipeStderr[1]; - si.wShowWindow = SW_HIDE; + // when the std IO is redirected, we don't show the (console) process + // window by default, but this can be overridden by the caller by + // specifying wxEXEC_NOHIDE flag + if ( !(flags & wxEXEC_NOHIDE) ) + { + si.dwFlags |= STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + } // we must duplicate the handle to the write side of stdin pipe to make // it non inheritable: indeed, we must close hpipeStdin[1] before @@ -587,7 +593,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) wxLogSysError(_("Execution of command '%s' failed"), command.c_str()); - return sync ? -1 : 0; + return flags & wxEXEC_SYNC ? -1 : 0; } #if wxUSE_STREAMS @@ -632,8 +638,8 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) data->hProcess = pi.hProcess; data->dwProcessId = pi.dwProcessId; data->hWnd = hwnd; - data->state = sync; - if ( sync ) + data->state = (flags & wxEXEC_SYNC) != 0; + if ( flags & wxEXEC_SYNC ) { // handler may be !NULL for capturing program output, but we don't use // it wxExecuteData struct in this case @@ -712,7 +718,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) } #endif // wxUSE_IPC - if ( !sync ) + if ( !(flags & wxEXEC_SYNC) ) { // clean up will be done when the process terminates @@ -742,21 +748,24 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) return dwExitCode; #else // Win16 long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW); - if (instanceID < 32) return(0); + if (instanceID < 32) + return flags & wxEXEC_SYNC ? -1 : 0; - if (sync) { + if ( flags & wxEXEC_SYNC ) + { int running; - do { + do + { wxYield(); running = GetModuleUsage((HINSTANCE)instanceID); } while (running); } - return(instanceID); + return instanceID; #endif // Win16/32 } -long wxExecute(char **argv, bool sync, wxProcess *handler) +long wxExecute(char **argv, int flags, wxProcess *handler) { wxString command; @@ -767,6 +776,6 @@ long wxExecute(char **argv, bool sync, wxProcess *handler) command.RemoveLast(); - return wxExecute(command, sync, handler); + return wxExecute(command, flags, handler); } diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index da7aa73531..83e04373a4 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -187,7 +187,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *rc) #define WXEXECUTE_NARGS 127 -long wxExecute( const wxString& command, bool sync, wxProcess *process ) +long wxExecute( const wxString& command, int flags, wxProcess *process ) { wxCHECK_MSG( !command.IsEmpty(), 0, wxT("can't exec empty command") ); @@ -247,7 +247,7 @@ long wxExecute( const wxString& command, bool sync, wxProcess *process ) argv[argc] = NULL; // do execute the command - long lRc = wxExecute(argv, sync, process); + long lRc = wxExecute(argv, flags, process); // clean up argc = 0; @@ -280,7 +280,7 @@ static wxString wxMakeShellCommand(const wxString& command) bool wxShell(const wxString& command) { - return wxExecute(wxMakeShellCommand(command), TRUE /* sync */) == 0; + return wxExecute(wxMakeShellCommand(command), wxEXEC_SYNC) == 0; } bool wxShell(const wxString& command, wxArrayString& output) @@ -519,7 +519,7 @@ wxStreamTempBuffer::~wxStreamTempBuffer() #endif // wxUSE_STREAMS long wxExecute(wxChar **argv, - bool sync, + int flags, wxProcess *process) { // for the sync execution, we return -1 to indicate failure, but for async @@ -527,7 +527,7 @@ long wxExecute(wxChar **argv, // // we define this as a macro, not a variable, to avoid compiler warnings // about "ERROR_RETURN_CODE value may be clobbered by fork()" - #define ERROR_RETURN_CODE ((sync) ? -1 : 0) + #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0) wxCHECK_MSG( *argv, ERROR_RETURN_CODE, wxT("can't exec empty command") ); @@ -632,7 +632,7 @@ long wxExecute(wxChar **argv, // input/output which might block the process or irritate the user. If // one wants proper IO for the subprocess, the right thing to do is to // start an xterm executing it. - if ( !sync ) + if ( !(flags & wxEXEC_SYNC) ) { for ( int fd = 0; fd < FD_SETSIZE; fd++ ) { @@ -710,7 +710,7 @@ long wxExecute(wxChar **argv, #if wxUSE_GUI && !defined(__WXMICROWIN__) wxEndProcessData *data = new wxEndProcessData; - if ( sync ) + if ( flags & wxEXEC_SYNC ) { // we may have process for capturing the program output, but it's // not used in wxEndProcessData in the case of sync execution @@ -759,7 +759,9 @@ long wxExecute(wxChar **argv, return pid; } #else // !wxUSE_GUI - wxASSERT_MSG( sync, wxT("async execution not supported yet") ); + + wxASSERT_MSG( flags & wxEXEC_SYNC, + wxT("async execution not supported yet") ); int exitcode = 0; if ( waitpid(pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) ) -- 2.45.2