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
This commit is contained in:
Vadim Zeitlin
2002-03-23 01:22:17 +00:00
parent 7841e80fa1
commit fbf456aa89
4 changed files with 86 additions and 39 deletions

View File

@@ -424,9 +424,9 @@ processes.
\membersection{::wxExecute}\label{wxexecute} \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}} \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 The semantics of the third and fourth versions is different from the first two
and is described in more details below. and is described in more details below.
If {\it sync} is FALSE (the default), flow of control immediately returns. If {\it flags} parameter contains {\tt wxEXEC\_ASYNC} flag (the default), flow
If TRUE, the current application waits until the other program has terminated. 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 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 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 and only this, case the calling code will not get the notification about
process termination. process termination.
If callback isn't NULL and if execution is asynchronous (note that callback If callback isn't NULL and if execution is asynchronous,
parameter can not be non-NULL for synchronous execution),
\helpref{wxProcess::OnTerminate}{wxprocessonterminate} will be called when \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 Finally, you may use the third overloaded version of this function to execute
a process (always synchronously) and capture its output in the array 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}, See also \helpref{wxShell}{wxshell}, \helpref{wxProcess}{wxprocess},
\helpref{Exec sample}{sampleexec}. \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} \wxheading{Include files}
<wx/utils.h> <wx/utils.h>

View File

@@ -148,17 +148,33 @@ WXDLLEXPORT wxString wxDecToHex(int dec);
// Process management // Process management
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Execute another program. Returns 0 if there was an error, a PID otherwise. // NB: for backwars compatibility reasons the values of wxEXEC_[A]SYNC *must*
WXDLLEXPORT long wxExecute(wxChar **argv, bool sync = FALSE, // 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); 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); 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, WXDLLEXPORT long wxExecute(const wxString& command,
wxArrayString& output); wxArrayString& output);
// also capture stderr // also capture stderr (also synchronous)
WXDLLEXPORT long wxExecute(const wxString& command, WXDLLEXPORT long wxExecute(const wxString& command,
wxArrayString& output, wxArrayString& output,
wxArrayString& error); wxArrayString& error);

View File

@@ -360,7 +360,7 @@ static bool wxExecuteDDE(const wxString& ddeServer,
#endif // wxUSE_IPC #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") ); 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 // 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 // the process is already running - but as it fails if it's not
// running, suppress any errors it might generate // running, suppress any errors it might generate
if ( !sync ) if ( !(flags & wxEXEC_SYNC) )
{ {
wxLogNull noErrors; wxLogNull noErrors;
if ( wxExecuteDDE(ddeServer, ddeTopic, ddeCommand) ) 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")); wxLogSysError(_("Can't create the inter-process read pipe"));
// indicate failure in both cases // indicate failure: we need to return different error code
return sync ? -1 : 0; // depending on the sync flag
return flags & wxEXEC_SYNC ? -1 : 0;
} }
// and a stdout one // 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")); 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); (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 wxUSE_STREAMS
if ( redirect ) if ( redirect )
{ {
// when the std IO is redirected, we don't show the (console) process si.dwFlags = STARTF_USESTDHANDLES;
// window
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.hStdInput = hpipeStdin[0]; si.hStdInput = hpipeStdin[0];
si.hStdOutput = hpipeStdout[1]; si.hStdOutput = hpipeStdout[1];
si.hStdError = hpipeStderr[1]; si.hStdError = hpipeStderr[1];
// 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; si.wShowWindow = SW_HIDE;
}
// we must duplicate the handle to the write side of stdin pipe to make // we must duplicate the handle to the write side of stdin pipe to make
// it non inheritable: indeed, we must close hpipeStdin[1] before // 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()); wxLogSysError(_("Execution of command '%s' failed"), command.c_str());
return sync ? -1 : 0; return flags & wxEXEC_SYNC ? -1 : 0;
} }
#if wxUSE_STREAMS #if wxUSE_STREAMS
@@ -632,8 +638,8 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
data->hProcess = pi.hProcess; data->hProcess = pi.hProcess;
data->dwProcessId = pi.dwProcessId; data->dwProcessId = pi.dwProcessId;
data->hWnd = hwnd; data->hWnd = hwnd;
data->state = sync; data->state = (flags & wxEXEC_SYNC) != 0;
if ( sync ) if ( flags & wxEXEC_SYNC )
{ {
// handler may be !NULL for capturing program output, but we don't use // handler may be !NULL for capturing program output, but we don't use
// it wxExecuteData struct in this case // it wxExecuteData struct in this case
@@ -712,7 +718,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
} }
#endif // wxUSE_IPC #endif // wxUSE_IPC
if ( !sync ) if ( !(flags & wxEXEC_SYNC) )
{ {
// clean up will be done when the process terminates // clean up will be done when the process terminates
@@ -742,21 +748,24 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
return dwExitCode; return dwExitCode;
#else // Win16 #else // Win16
long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW); 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; int running;
do { do
{
wxYield(); wxYield();
running = GetModuleUsage((HINSTANCE)instanceID); running = GetModuleUsage((HINSTANCE)instanceID);
} while (running); } while (running);
} }
return(instanceID); return instanceID;
#endif // Win16/32 #endif // Win16/32
} }
long wxExecute(char **argv, bool sync, wxProcess *handler) long wxExecute(char **argv, int flags, wxProcess *handler)
{ {
wxString command; wxString command;
@@ -767,6 +776,6 @@ long wxExecute(char **argv, bool sync, wxProcess *handler)
command.RemoveLast(); command.RemoveLast();
return wxExecute(command, sync, handler); return wxExecute(command, flags, handler);
} }

View File

@@ -187,7 +187,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *rc)
#define WXEXECUTE_NARGS 127 #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") ); 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; argv[argc] = NULL;
// do execute the command // do execute the command
long lRc = wxExecute(argv, sync, process); long lRc = wxExecute(argv, flags, process);
// clean up // clean up
argc = 0; argc = 0;
@@ -280,7 +280,7 @@ static wxString wxMakeShellCommand(const wxString& command)
bool wxShell(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) bool wxShell(const wxString& command, wxArrayString& output)
@@ -519,7 +519,7 @@ wxStreamTempBuffer::~wxStreamTempBuffer()
#endif // wxUSE_STREAMS #endif // wxUSE_STREAMS
long wxExecute(wxChar **argv, long wxExecute(wxChar **argv,
bool sync, int flags,
wxProcess *process) wxProcess *process)
{ {
// for the sync execution, we return -1 to indicate failure, but for async // 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 // we define this as a macro, not a variable, to avoid compiler warnings
// about "ERROR_RETURN_CODE value may be clobbered by fork()" // 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") ); 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 // 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 // one wants proper IO for the subprocess, the right thing to do is to
// start an xterm executing it. // start an xterm executing it.
if ( !sync ) if ( !(flags & wxEXEC_SYNC) )
{ {
for ( int fd = 0; fd < FD_SETSIZE; fd++ ) for ( int fd = 0; fd < FD_SETSIZE; fd++ )
{ {
@@ -710,7 +710,7 @@ long wxExecute(wxChar **argv,
#if wxUSE_GUI && !defined(__WXMICROWIN__) #if wxUSE_GUI && !defined(__WXMICROWIN__)
wxEndProcessData *data = new wxEndProcessData; wxEndProcessData *data = new wxEndProcessData;
if ( sync ) if ( flags & wxEXEC_SYNC )
{ {
// we may have process for capturing the program output, but it's // we may have process for capturing the program output, but it's
// not used in wxEndProcessData in the case of sync execution // not used in wxEndProcessData in the case of sync execution
@@ -759,7 +759,9 @@ long wxExecute(wxChar **argv,
return pid; return pid;
} }
#else // !wxUSE_GUI #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; int exitcode = 0;
if ( waitpid(pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) ) if ( waitpid(pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) )