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:
@@ -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>
|
||||||
|
@@ -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);
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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) )
|
||||||
|
Reference in New Issue
Block a user