Process Management

Creating a Process

There are many answers to this, depending on what you need to accomplish. The old-fashioned C functions spawn and system still work. However, these are considered somewhat obsolete. They don't give you the control you need to receive a notification that the process completed, because you can't get the process handle.

The underlying Win32 API call to spawn a process is ::CreateProcess. This also gives you the ability to specify, for a windowing application, where on the screen the window will appear. However, ::CreateProcess is the lowest-level interface to process spawning. Microsoft recommends you use ShellExecute, which is still not good enough; while it provides the high-level interface for the best integration into the Windows environment (for example, you can give it a URL and it will launch Internet Explorer automatically if it is not running, or send the request directly to a running instance) it still doesn't provide what you need to receive a notification.

To determine if a process has stopped, you will need a process handle. This is the token Win32 uses to represent a process to an application. You can get the process handle by using either ::CreateProcess or ::ShellExecuteEx. For the best integration into Windows, Microsoft suggests (urges, demands) that you use ::ShellExecute.

Here are two examples of how to get the process handle and store it in a variable hProcess: In both cases, the functions are called with the name of the program to launch and a pointer to any arguments for its command line. If there are no arguments, the argument pointer can be NULL. The functions return a HANDLE to the process that was created, or NULL if they failed to create a process. If they return NULL, the caller can call ::GetLastError() to determine what went wrong. Note that these are "bare bones" launchers; if you want fancy control of position, startup state, console state, initial view, etc. you can work theme-and-variations on these schemes. If you want to launch a console-mode program and feed information to stdin or receive data from stdout, you will have to use ::CreateProcess, but that's the subject of another essay.

HANDLE launchViaCreateProcess(LPCTSTR program, LPCTSTR args)
    {
     HANDLE hProcess = NULL;
     PROCESSINFO processInfo;
     STARTUPINFO startupInfo;
     ::ZeroMemory(&startupInfo, sizeof(startupInfo));
     startupInfo.cb = sizeof(startupInfo);
     if(::CreateProcess(program, (LPTSTR)args, 
                        NULL,  // process security
                        NULL,  // thread security
                        FALSE, // no inheritance
                        0,     // no startup flags
                        NULL,  // no special environment
                        NULL,  // default startup directory
                        &startupInfo,
                        &processInfo))
        { /* success */
         hProcess = processInfo.hProcess;
        } /* success */
     return hProcess;
    }
HANDLE launchViaShellExecute(LPCTSTR program, LPCTSTR args)
    {
     HANDLE hProcess = NULL;
     SHELLEXECUTEINFO shellInfo;
     ::ZeroMemory(&shellInfo, sizeof(shellInfo));
     shellInfo.cbSize = sizeof(shellInfo);
     shellInfo.fMask = SEE_MASK_NOUI | SEE_MASK_NOCLOSEPROCESS;
     shellInfo.lpFile = program;
     shellInfo.lpParameters = args;
     if(::ShellExecuteEx(&shellInfo))
        { /* success */
         hProcess = shellInfo.hProcess;
        } /* success */
     return hProcess;
    }

The nature of Windows is that a launched process takes on a life of its own. If you have a Unix background, there is nothing like the "process groups" of Unix. Once a process is launched, it has a life of its own. You have explicit control of it if you retain the process handle (and the window handle, if you get that), but if your process dies, any processes you started keep right on running. The aliveness or deadness of your process has no effect on them, unless of course they were waiting for your process to do something for them (like supply stdin text). In this case, they won't die, but they will block waiting for the desired event. So if you want to terminate a process, you have to provide a way of accomplishing this.

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Engineers are all basically high-functioning autistics who have no idea how normal people do stuff.” - Cory Doctorow