the exit code of the process and not its pid. Warning: MSW code is untested.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1712
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
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 sync} is FALSE (the default), flow of control immediately returns.
If TRUE, the current application waits until the other program has terminated.
-The return value is the process id, not the exit code of invoked program (for
-this you should use wxProcess). A zero value indicates that the command could
-not be executed.
+In the case of synchronous execution, the return value is trhe exit code of
+the process (which terminates by the moment the function returns) and will be
+$-1$ if the process couldn't be started and typically 0 if the process
+terminated successfully.
+
+For asynchronous execution, however, the return value is the process id and
+zero value indicates that the command could not be executed.
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 (note that callback
parameter can not be non NULL for synchronous execution),
// subprocess routines
//------------------------------------------------------------------------
// subprocess routines
//------------------------------------------------------------------------
+// if pid > 0, the execution is async and the data is freed in
+// GTK_EndProcessDetector, if pid < 0, the execution is synchronous and the
+// caller (wxExecute) frees the data
struct wxEndProcessData
{
gint pid, tag;
wxProcess *process;
struct wxEndProcessData
{
gint pid, tag;
wxProcess *process;
};
static void GTK_EndProcessDetector(gpointer data, gint source,
};
static void GTK_EndProcessDetector(gpointer data, gint source,
// one)
int status = -1;
#if !defined(__sgi)
// one)
int status = -1;
#if !defined(__sgi)
- wait4(proc_data->pid, &status, 0, (rusage *) NULL);
+ wait4(pid, &status, 0, (rusage *) NULL);
#else
wait3(&status, 0, (rusage *) NULL);
#endif
#else
wait3(&status, 0, (rusage *) NULL);
#endif
proc_data->process->OnTerminate(proc_data->pid, status);
if (proc_data->pid > 0)
proc_data->process->OnTerminate(proc_data->pid, status);
if (proc_data->pid > 0)
+ {
+ // wxExecute() will know about it
+ proc_data->exitcode = status;
+
}
long wxExecute( char **argv, bool sync, wxProcess *process )
}
long wxExecute( char **argv, bool sync, wxProcess *process )
close(end_proc_detect[1]); // close writing side
data->tag = gdk_input_add(end_proc_detect[0], GDK_INPUT_READ,
GTK_EndProcessDetector, (gpointer)data);
close(end_proc_detect[1]); // close writing side
data->tag = gdk_input_add(end_proc_detect[0], GDK_INPUT_READ,
GTK_EndProcessDetector, (gpointer)data);
- data->pid = pid;
- if (!sync)
- {
- data->process = process;
- }
- else
- data->process = process;
- data->pid = -(data->pid);
+ wxASSERT_MSG( !process, "wxProcess param ignored for sync exec" );
+ data->process = NULL;
+
+ // sync execution: indicate it by negating the pid
+ data->pid = -pid;
+ // it will be set to 0 from GTK_EndProcessDetector
while (data->pid != 0)
wxYield();
while (data->pid != 0)
wxYield();
+ int exitcode = data->exitcode;
+
+ else
+ {
+ // async execution, nothing special to do - caller will be
+ // notified about the process terminationif process != NULL, data
+ // will be deleted in GTK_EndProcessDetector
+ data->process = process;
+ data->pid = pid;
- // @@@ our return value indicates success even if execvp() in the child
- // failed!
- return pid;
// subprocess routines
//------------------------------------------------------------------------
// subprocess routines
//------------------------------------------------------------------------
+// if pid > 0, the execution is async and the data is freed in
+// GTK_EndProcessDetector, if pid < 0, the execution is synchronous and the
+// caller (wxExecute) frees the data
struct wxEndProcessData
{
gint pid, tag;
wxProcess *process;
struct wxEndProcessData
{
gint pid, tag;
wxProcess *process;
};
static void GTK_EndProcessDetector(gpointer data, gint source,
};
static void GTK_EndProcessDetector(gpointer data, gint source,
// one)
int status = -1;
#if !defined(__sgi)
// one)
int status = -1;
#if !defined(__sgi)
- wait4(proc_data->pid, &status, 0, (rusage *) NULL);
+ wait4(pid, &status, 0, (rusage *) NULL);
#else
wait3(&status, 0, (rusage *) NULL);
#endif
#else
wait3(&status, 0, (rusage *) NULL);
#endif
proc_data->process->OnTerminate(proc_data->pid, status);
if (proc_data->pid > 0)
proc_data->process->OnTerminate(proc_data->pid, status);
if (proc_data->pid > 0)
+ {
+ // wxExecute() will know about it
+ proc_data->exitcode = status;
+
}
long wxExecute( char **argv, bool sync, wxProcess *process )
}
long wxExecute( char **argv, bool sync, wxProcess *process )
close(end_proc_detect[1]); // close writing side
data->tag = gdk_input_add(end_proc_detect[0], GDK_INPUT_READ,
GTK_EndProcessDetector, (gpointer)data);
close(end_proc_detect[1]); // close writing side
data->tag = gdk_input_add(end_proc_detect[0], GDK_INPUT_READ,
GTK_EndProcessDetector, (gpointer)data);
- data->pid = pid;
- if (!sync)
- {
- data->process = process;
- }
- else
- data->process = process;
- data->pid = -(data->pid);
+ wxASSERT_MSG( !process, "wxProcess param ignored for sync exec" );
+ data->process = NULL;
+
+ // sync execution: indicate it by negating the pid
+ data->pid = -pid;
+ // it will be set to 0 from GTK_EndProcessDetector
while (data->pid != 0)
wxYield();
while (data->pid != 0)
wxYield();
+ int exitcode = data->exitcode;
+
+ else
+ {
+ // async execution, nothing special to do - caller will be
+ // notified about the process terminationif process != NULL, data
+ // will be deleted in GTK_EndProcessDetector
+ data->process = process;
+ data->pid = pid;
- // @@@ our return value indicates success even if execvp() in the child
- // failed!
- return pid;
// send a message indicating process termination to the window
SendMessage(data->hWnd, wxWM_PROC_TERMINATED, 0, (LPARAM)data);
// send a message indicating process termination to the window
SendMessage(data->hWnd, wxWM_PROC_TERMINATED, 0, (LPARAM)data);
data->handler->OnTerminate((int)data->dwProcessId,
(int)data->dwExitCode);
}
data->handler->OnTerminate((int)data->dwProcessId,
(int)data->dwExitCode);
}
if ( data->state )
{
// we're executing synchronously, tell the waiting thread
if ( data->state )
{
// we're executing synchronously, tell the waiting thread
result = ShellExecute(hwndTop, "open", commandName,
commandArgs, NULL, SW_SHOWNORMAL);
#endif // GNUWIN32
result = ShellExecute(hwndTop, "open", commandName,
commandArgs, NULL, SW_SHOWNORMAL);
#endif // GNUWIN32
if ( ((long)result) <= 32 )
wxLogSysError(_("Can't execute command '%s'"), command.c_str());
if ( ((long)result) <= 32 )
wxLogSysError(_("Can't execute command '%s'"), command.c_str());
HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL,
(HMENU)NULL, wxGetInstance(), 0);
wxASSERT_MSG( hwnd, "can't create a hidden window for wxExecute" );
HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL,
(HMENU)NULL, wxGetInstance(), 0);
wxASSERT_MSG( hwnd, "can't create a hidden window for wxExecute" );
FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
wxGetInstance());
FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk,
wxGetInstance());
::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance);
// Alloc data
wxExecuteData *data = new wxExecuteData;
data->hProcess = pi.hProcess;
data->dwProcessId = pi.dwProcessId;
data->hWnd = hwnd;
data->state = sync;
// Alloc data
wxExecuteData *data = new wxExecuteData;
data->hProcess = pi.hProcess;
data->dwProcessId = pi.dwProcessId;
data->hWnd = hwnd;
data->state = sync;
- data->handler = handler;
+ if ( sync )
+ {
+ wxASSERT_MSG( !handler, "wxProcess param ignored for sync execution" );
+
+ data->handler = NULL;
+ }
+ else
+ {
+ // may be NULL or not
+ data->handler = handler;
+ }
DWORD tid;
HANDLE hThread = ::CreateThread(NULL,
DWORD tid;
HANDLE hThread = ::CreateThread(NULL,
// the process still started up successfully...
return pi.dwProcessId;
}
// the process still started up successfully...
return pi.dwProcessId;
}
if ( !sync )
{
// clean up will be done when the process terminates
if ( !sync )
{
// clean up will be done when the process terminates
// waiting until command executed
while ( data->state )
wxYield();
// waiting until command executed
while ( data->state )
wxYield();
+
+ DWORD dwExitCode = data->dwExitCode;
+ // return the exit code
+ return dwExitCode;
#endif // 0/1
#else // Win16
long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW);
if (instanceID < 32) return(0);
#endif // 0/1
#else // Win16
long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW);
if (instanceID < 32) return(0);
if (sync) {
int running;
do {
if (sync) {
int running;
do {
long wxExecute(char **argv, bool sync, wxProcess *handler)
{
wxString command;
long wxExecute(char **argv, bool sync, wxProcess *handler)
{
wxString command;
while ( *argv != NULL )
{
command << *argv++ << ' ';
while ( *argv != NULL )
{
command << *argv++ << ' ';