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}
\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}
<wx/utils.h>

View File

@ -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);

View File

@ -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);
}

View File

@ -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) )