- use wxStream::GetLength() instead of deprecated GetSize()
- wxGetOsDescription() is now more precise (Olly Betts)
- XRC supports system fonts and colours (Ray Gilbert)
+- Added flags argument to wxKill/wxProcess::Kill to kill child processes.
All (GUI):
Under Unix the flag {\tt wxEXEC\_MAKE\_GROUP\_LEADER} may be used to ensure
that the new process is a group leader (this will create a new session if
-needed). Calling \helpref{wxKill}{wxkill} with the argument of -pid where pid
-is the process ID of the new process will kill this process as well as all of
-its children (except those which have started their own session).
+needed). Calling \helpref{wxKill}{wxkill} passing wxKILL\_CHILDREN will
+will kill this process as well as all of its children (except those which have
+started their own session).
Finally, you may use the third overloaded version of this function to execute
a process (always synchronously) and capture its output in the array
\membersection{::wxKill}\label{wxkill}
-\func{int}{wxKill}{\param{long}{ pid}, \param{int}{ sig = wxSIGTERM}, \param{wxKillError }{*rc = NULL}}
+\func{int}{wxKill}{\param{long}{ pid}, \param{int}{ sig = wxSIGTERM}, \param{wxKillError }{*rc = NULL}, \param{int }{flags = 0}}
Equivalent to the Unix kill function: send the given signal {\it sig} to the
process with PID {\it pid}. The valid signal values are
};
\end{verbatim}
+The {\it flags} parameter can be wxKILL\_NOCHILDREN (the default),
+or wxKILL\_CHILDREN, in which case the child processes of this
+process will be killed too. Note that under Unix, for wxKILL\_CHILDREN
+to work you should have created the process by passing wxEXEC\_MAKE_GROUP\_LEADER
+to wxExecute.
+
\wxheading{See also}
\helpref{wxProcess::Kill}{wxprocesskill},\rtfsp
\membersection{wxProcess::Kill}\label{wxprocesskill}
-\func{static wxKillError}{Kill}{\param{int}{ pid}, \param{wxSignal}{ signal = wxSIGNONE}}
+\func{static wxKillError}{Kill}{\param{int}{ pid}, \param{wxSignal}{ signal = wxSIGNONE}, \param{int }{flags = wxKILL\_NOCHILDREN}}
Send the specified signal to the given process. Possible signal values are:
under both Unix and Windows but all the other signals are equivalent to
{\tt wxSIGTERM} under Windows.
+The {\it flags} parameter can be wxKILL\_NOCHILDREN (the default),
+or wxKILL\_CHILDREN, in which case the child processes of this
+process will be killed too. Note that under Unix, for wxKILL\_CHILDREN
+to work you should have created the process passing wxEXEC\_MAKE_GROUP\_LEADER.
+
Returns the element of {\tt wxKillError} enum:
\begin{verbatim}
{
public:
// kill the process with the given PID
- static wxKillError Kill(int pid, wxSignal sig = wxSIGTERM);
+ static wxKillError Kill(int pid, wxSignal sig = wxSIGTERM, int flags = wxKILL_NOCHILDREN);
// test if the given process exists
static bool Exists(int pid);
// Process management
// ----------------------------------------------------------------------------
-// NB: for backwars compatibility reasons the values of wxEXEC_[A]SYNC *must*
+// NB: for backwards compatibility reasons the values of wxEXEC_[A]SYNC *must*
// be 0 and 1, don't change!
enum
// is done by default)
wxEXEC_NOHIDE = 2,
- // under Unix, if the process is the group leader then killing -pid kills
- // all children as well as pid
+ // under Unix, if the process is the group leader then passing wxKILL_CHILDREN to wxKill
+ // kills all children as well as pid
wxEXEC_MAKE_GROUP_LEADER = 4
};
wxKILL_ERROR // another, unspecified error
};
+enum wxKillFlags
+{
+ wxKILL_NOCHILDREN = 0, // don't kill children
+ wxKILL_CHILDREN = 1 // kill children
+};
+
enum wxShutdownFlags
{
wxSHUTDOWN_POWEROFF, // power off the computer
// return detailed error in rc if not NULL
WXDLLIMPEXP_BASE int wxKill(long pid,
wxSignal sig = wxSIGTERM,
- wxKillError *rc = NULL);
+ wxKillError *rc = NULL,
+ int flags = wxKILL_NOCHILDREN);
// Execute a command in an interactive shell window (always synchronously)
// If no command then just the shell
// ----------------------------------------------------------------------------
/* static */
-wxKillError wxProcess::Kill(int pid, wxSignal sig)
+wxKillError wxProcess::Kill(int pid, wxSignal sig, int flags)
{
wxKillError rc;
- (void)wxKill(pid, sig, &rc);
+ (void)wxKill(pid, sig, &rc, flags);
return rc;
}
return TRUE;
}
-int wxKill(long pid, wxSignal sig , wxKillError *rc )
+int wxKill(long pid, wxSignal sig , wxKillError *rc, int flags)
{
// TODO
return 0;
return TRUE;
}
-int wxKill(long pid, wxSignal sig , wxKillError *rc )
+int wxKill(long pid, wxSignal sig , wxKillError *rc, int flags)
{
// TODO
return 0;
#endif
#endif
+// For wxKillAllChildren
+#include <tlhelp32.h>
+
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
return TRUE;
}
-int wxKill(long pid, wxSignal sig, wxKillError *krc)
+int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc);
+
+int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
{
+ if (flags & wxKILL_CHILDREN)
+ wxKillAllChildren(pid, sig, krc);
+
// get the process handle to operate on
HANDLE hProcess = ::OpenProcess(SYNCHRONIZE |
PROCESS_TERMINATE |
return -1;
}
+HANDLE (WINAPI *lpfCreateToolhelp32Snapshot)(DWORD,DWORD) ;
+BOOL (WINAPI *lpfProcess32First)(HANDLE,LPPROCESSENTRY32) ;
+BOOL (WINAPI *lpfProcess32Next)(HANDLE,LPPROCESSENTRY32) ;
+
+static void InitToolHelp32()
+{
+ static bool s_initToolHelpDone = false;
+
+ if (s_initToolHelpDone)
+ return;
+
+ s_initToolHelpDone = true;
+
+ lpfCreateToolhelp32Snapshot = NULL;
+ lpfProcess32First = NULL;
+ lpfProcess32Next = NULL;
+
+ HINSTANCE hInstLib = LoadLibraryA( "Kernel32.DLL" ) ;
+ if( hInstLib == NULL )
+ return ;
+
+ // Get procedure addresses.
+ // We are linking to these functions of Kernel32
+ // explicitly, because otherwise a module using
+ // this code would fail to load under Windows NT,
+ // which does not have the Toolhelp32
+ // functions in the Kernel 32.
+ lpfCreateToolhelp32Snapshot=
+ (HANDLE(WINAPI *)(DWORD,DWORD))
+ GetProcAddress( hInstLib,
+ "CreateToolhelp32Snapshot" ) ;
+
+ lpfProcess32First=
+ (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
+ GetProcAddress( hInstLib, "Process32First" ) ;
+
+ lpfProcess32Next=
+ (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
+ GetProcAddress( hInstLib, "Process32Next" ) ;
+
+ FreeLibrary( hInstLib ) ;
+}
+
+// By John Skiff
+int wxKillAllChildren(long pid, wxSignal sig, wxKillError *krc)
+{
+ InitToolHelp32();
+
+ if (krc)
+ *krc = wxKILL_OK;
+
+ // If not implemented for this platform (e.g. NT 4.0), silently ignore
+ if (!lpfCreateToolhelp32Snapshot || !lpfProcess32First || !lpfProcess32Next)
+ return 0;
+
+ // Take a snapshot of all processes in the system.
+ HANDLE hProcessSnap = lpfCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+ if (hProcessSnap == INVALID_HANDLE_VALUE) {
+ if (krc)
+ *krc = wxKILL_ERROR;
+ return -1;
+ }
+
+ //Fill in the size of the structure before using it.
+ PROCESSENTRY32 pe = {0};
+ pe.dwSize = sizeof(PROCESSENTRY32);
+
+ // Walk the snapshot of the processes, and for each process,
+ // kill it if its parent is pid.
+ if (!lpfProcess32First(hProcessSnap, &pe)) {
+ // Can't get first process.
+ if (krc)
+ *krc = wxKILL_ERROR;
+ CloseHandle (hProcessSnap);
+ return -1;
+ }
+
+ do {
+ if (pe.th32ParentProcessID == (DWORD) pid) {
+ if (wxKill(pe.th32ProcessID, sig, krc))
+ return -1;
+ }
+ } while (lpfProcess32Next (hProcessSnap, &pe));
+
+
+ return 0;
+}
+
// Execute a program in an Interactive Shell
bool wxShell(const wxString& command)
{
long lPid
, wxSignal eSig
, wxKillError* peError
+, int flags
)
{
return((int)::DosKillProcess(0, (PID)lPid));
// process management
// ----------------------------------------------------------------------------
-// structure used to pass parameters from wxKill() to wxEnumFindByPidProc()
-int wxKill(long pid, wxSignal sig, wxKillError *krc)
+int wxKill(long pid, wxSignal sig, wxKillError *krc, int flags)
{
return 0;
}
// process management
// ----------------------------------------------------------------------------
-int wxKill(long pid, wxSignal sig, wxKillError *rc)
+int wxKill(long pid, wxSignal sig, wxKillError *rc, int flags)
{
- int err = kill((pid_t)pid, (int)sig);
+ int err = kill((pid_t) (flags & wxKILL_CHILDREN) ? -pid : pid, (int)sig);
if ( !err )
*rc = wxKILL_OK;
else