Next Previous Table of Contents

### 8. Process Handling

The KDE UI library provides the classes `KProcess` and `KShellProcess` to run external processes that are invoked within the application that needs to run another application. This has generally two advantages:

- you don't have to reinvent the wheel when commandline programs already exist
- your application's event queue is not blocked by long operations

A lot of applications already make wide use of these classes as they are very flexible and provide the necessary interface not only to start another application but to control its output and termination. As mentioned, a lot of Unix applications are already available but only work on commandline. The commandline arguments are hard to remember and most users won't ever touch them if they don't need them really. For occasional usage, the interface is too complex and therefore not very user-friendly. As KDE applications target a desktop system where even unexperienced users can feel themselves at home, this is the best way to write so-called front-ends for terminal applications.

Another possible use even for KDE programmers would be to write their target application as a commandline program and provide a user-friendly GUI interface.

The following sections will describe the `KProcess` class first, then the usage of `KShellProcess`, as this is a subclass of `KProcess`, therefore differs only in its usage.

### 8.1 KProcess

The `KProcess` class is based on `QObject`, therefore able to communicate by signals and slots. It can be used to start any executable binary as a child process on the local system and control it by communication and run mode. To use `KProcess`, include `kprocess.h` and create an instance of `KProcess`. If the instance has been created and used already, you have to call `clearArguments()` to ensure the arguments are empty before the next usage. The actual usage is to transmit the complete commandline argument to the process instance using the operator << as strings. Then the actual process is called with `start()`. This function has to be called with the run mode and communication.

#### Run mode

The run mode of the external application can be set when calling `start()` as the first argument. The run mode can be one of `DontCare, NotifyOnExit, Block`. Now, what does this mean to the application that is called and to the application that calls the process ?

- DontCare: The child process is called and started with the given commandline arguments. Easy to guess, DontCare means that the caller is not interested if the child process has exited or not. The two applications run concurrently, but the invoking process (usually the GUI application) doesn't get notified and runs like without starting any process.
- NotifyOnExit: both processes run concurrently like in DontCare run mode. The difference is that the process controller can emit the signal `processExited()`, which can be caught to determine the child process has finished. The notification can be used to reset any statusbar message informing the user that the process is running, this should be used as a guideline to inform the user about the current state of the application. Mind that the invoking application is responsible for the child process as it is unlikely that non-experienced users will control and other process that they see.
- Block: the child process blocks the caller's event handling and program execution. This is not recommended to use within GUI applications as even the call `processEvents()` won't be executed; therefore the event handling cannot be called to execute even by event precedence.

The `start()` method also returns if the start has been successful or not. Therefore you should always call the method with an `if()` statement to display a message box if starting the process returns false. Reasons for `start()` to return false could be:

- the commandline argument list is empty (which is your implementations's fault)
- the process which is to be called is already running
- starting the child process failed

To inform the user why the process cannot be executed, you have to investigate these three possibilities. The first possibility, an empty commandline, depends on your GUI that provides the methods setting the commandline options. Normally, you would retrieve them by a dialog where the user sets the options on how to start the application. The GUI for these dialogs normally uses radio buttons to let the user choose one of several options (or more if the process allows this), a lineedit for filenames (with an additional file-selection button to call a `KFileDialog::getOpenFileName()`), eventually a lineedit for output locations, also with a `KFileDialog::getSaveFileName()`.

The second possibility mostly occurs in situations where the application has been started twice or the user has opened another instance of its main window where or by which he caused another process call. In this case, you could use `getPid()` to determine the current process ID which can be used in a message box to show that the process is already running.

Finally, failing a call of a child process often means that the program is not available on the system. There, you should inform the user that he has to install the program to ensure functionality. Another option would be to test the `PATH` environment variable of the user for the directories he uses to call applications. Then you could test with `QFile::exists()`, if the binary is there even before trying to start it.

#### Communication

The communication with the caller process is another option that has to be set while calling `KProcess::start()`. With this, you can retrieve the output of the process where needed. The available communication modes are:

- NoCommunication : Use when you don't want to communicate with the process, e.g. it runs silently without interesting output or requiring any input.
- Stdin : To be used if the process asks for user input. Depending on the process, you have to use this communication mode to avoid blocking - the process just will wait for input but can never retrieve the information if this mode isn't used.
- Stdout : The output the process sends to StdOut, which would be your terminal for example. This mode has to be used if you want to retrieve the output information for displaying it to the user in a widget.
- Stderr : error messages sent by the process to StdErr can be retrieved seperately by this mode. This is useful to check for errors.
- AllOutput : Stdout and Stderr OR'ed together. Mind that this doesn't include StdIn communication !
- All: Open all communication channels, meaning that Stdout, Stderr and Stdin are OR'ed together.

As mentioned for `AllOutput` and `All` communication modes, the available modes can be OR'ed together to combine the needed modes.

By the according signals and slots, you can connect the communication data channels to e.g. a text widget or a buffer. Displaying the output directly into a text widget will be used for Stdout in most cases while error messages can as well be retrieved into a non-visible buffer which can be processed to visualize errors by messageboxes.

### 8.2 KShellProcess

The `KShellProcess` class is a specialized `KProcess` class. The main difference is that you can call your executable via a Unix shell which allows all options the selected shell offers. You should check for available shells as well before calling a shell process for a special shell; the normal constructor will check for any shell available but can be set to use e.g. /bin/bash to make use of the Bourne shell - but you can't expect any system to have the Bourne shell available. The use of a `KShellProcess` offers the following advantages:

- Useage of environment variables
- Setting environment variables
- pipe usage
- wildcard usage

The methods of `KProcess` then offer the necessary communication and runmodes the process may need.

Next Previous Table of Contents