Starting, Managing and Switching Processes
The demo is a Visual C++ 6 project.
In a few of my projects I have to deal with processes. To protect me from implementing all of the hard bits again and again, I developed a set of classes. These are mainly a process manager class and a process enumerator class.
The Process Enumerator Class CProcessList
This class makes it easy to take a snapshot of all currently running processes and iterate them. There is no need for you to determine the type of system your application is running on. The enumerator selects the best enumeration method available. Because of this fact, you cannot simply instantiate an object of the process enumerator. You have to "Create()" one instead:
CProcessList * pProcessList = CProcessList::Create();
Now that you have a valid object, you can take a snapshot of the process list:
pProcessList->SnapShot();
After having done this, you can iterate the processes:
CProcess * pProcess;
while((pProcess = pProcessList->GetNextProcess()) != 0) {
TRACE("process' filename: \"%s\" PID: %lu\n", LPCTSTR(pProcess->GetFilename()), pProcess->GetPID());
}
You can reuse the enumerator by taking another snapshot.
If you don't need the process enumerator any longer, you have to delete it:
delete pProcessList;
A detailed class documentation is inside the source archives.
The Process Manager Class CProcessMgr
CProcessMgr has the following member functions (description follows below):
// split a command string
BOOL ParseCommand(
const CString & CmdLine,
CString & Directory,
CString & Cmd,
CString & Args
); // execute a command
DWORD Execute(
const CString & strCmd,
const CString & strArgs,
const CString & strDir = "",
BOOL bWait = FALSE
);
DWORD Execute(
const CString & strCmdLine,
BOOL bWait = FALSE
); // wait for another process
DWORD Wait( DWORD PID ) const; // check wether a program is running
DWORD IsProgramRunning(const CString & FileName) const;
DWORD IsProgramRunning(DWORD PID) const; // switch to another running application
BOOL SwitchProcessIntoForeground(DWORD PID) const;
BOOL SwitchProcessIntoForeground( const CString & FileName ) const; // get informations about a shell-link (known as "shortcut")
BOOL GetLinkInfo(const CString & LinkName, CString & Path) const; // handle an error
virtual void OnExecError( int nErrorCode, const CString & strCommand );
One of the main goals of this class is, that it understands complex command strings. This is very useful since one can store such a command string in the registry (or in a file or database or whatever) at once. The syntax of such a command string is as follows (BNF-notation):
CmdLine : command
| command arguments
| 'cd' directory ';' command
| 'cd' directory ';' command arguments
command : string
arguments: string
| arguments string
directory: string /* shall consist of a full path ! */
string : '[^ \t]+' /* string without blanks/tabs */
| '"' '[^"]*' '"' /* quoted string can
contain any character
except " itself */
OK - not all of you are familiar with BNF, so let me give some examples:
cmd cmd /c dir cd C:\windows ; cmd /c dir cd "C:\Program Files\Informix" ; cmd /c dir cd "C:\Program Files\Pictures" ; "\\picard\Software\Graphic Utilities\PSP\psp.exe" Title.jpg
All of these are valid command strings. Note that these samples are not in C/C++ notation !
The Parse() method splits such a command string into its components "directory", "command" and "arguments". Any special
tokens are stripped off, so if you parse the last example, it would give you C:\Program Files\Pictures as the directory,
\\picard\Software\Graphic Utilities\PSP\psp.exe as the command and Title.jpg as the argument to the command. You can
pass a complete command string to the Execute() method. If the command part of the string is not an executable file, then
Execute() searches for the associated executable. The return value of Execute() depends on the <bWait> parameter. If
<bWait> is TRUE, then it returns the exit code of the execution, otherwise a process-ID (PID) will return.
With the Wait() method you can explicitly wait for the end of a running process; just give Wait() the process id of that
process.
To check whether a special program is currently running, you can use the IsProgramRunning() method. If you pass the name of an executable file, this method checks the process table and gives you the PID of the process or 0 (zero) if that program is currently not running. If you're developing an application, that does not provide a window, but this program must run only once per machine, you cannot use FindWindow() to determine, whether the application is already running. The use of mutexes or similar resources might be an inacceptable overhead too. In such a case, one can simply use the following code:
TCHAR szName[1024];
GetModuleFileName(0, szName, 1023);
if( CProcessMgr().IsProgramRunning(szName) != DWORD(getpid()) ) {
// the application is already running on this machine
}
The code above works correctly, because a newly created process appears after a previously created process in the process table, so the method finds the other application first.
At last: the SwitchProcessIntoForeground() method switches a process into the foreground; i.e. makes that process the active process. If the main window of that process is minimized, then it will be restored to its previous state. If IsProgramRunning() indicates that a certain Process is running and SwitchProcessIntoForeground() says "I cannot switch to that process", then the process is possibly a DDE/OLE server that has currently hidden windows only or it is a process without a window (an NT service for instance).
There is a detailed class documentation in either the source- and the sample archive (in the htmldocs subdirectory; start with index.html).
Download
The process manager/enumerator package consists of four files
ProcessMgr.[h|cpp]
Processes.[h|cpp]
Note that ProcessMgr.* depends on Processes.* ; but not vice versa (thus you can use the enumerator "stand alone").
Date Last Updated: April 18, 1999

Comments
Compilation under VC++ 2005
Posted by alexadvance on 01/30/2007 10:16amI can't compile it under Visual C++ 2005 : error C2664: 'std::list<_Ty>::_Iterator<_Secure_validation>::_Iterator(const std::list<_Ty>::_Iterator<_Secure_validation> &)' : impossible de convertir le paramC(tre 1 de 'int' en 'const std::list<_Ty>::_Iterator<_Secure_validation> &' Is there available up-to-date version ?
ReplyHow to check if an application in a DLL is running ?
Posted by lulacapixaba on 03/08/2005 11:53amThe code is very interesting but I think it would not work in some circumstances. Suppose you want to detect if the "Windows Picture and Fax Viewer" is running on your machine. This application is launched from a DLL in a command line similar to this one: rundll32.exe c:\windows\system32\shimgvw.dll,ImageView_Fullscreen C:\temp\logo.gif If you use your code to check if the application is running, it will not be abble to detect it. It would detect that RUNDLL32.EXE is running... but what about the "Windows Picture and Fax Viewer"? The problem I have at the moment is that I have a process handle and I want to know if I have an existing instance of this process runnig. I am not interested in the RUN32DLL.exe process but in the actual application that is inside the DLL. If I have multiple applications running from inside DLLs, how can I detect if they are running?
ReplyCProcessMgr under Win2000
Posted by Legacy on 07/10/2001 12:00amOriginally posted by: Markus Schroth
What do I have to Do that this very nice Code runs under Win2000 ( No Access ) ?
ReplyIf all you want to do is spawn and wait for completion...
Posted by Legacy on 05/05/1999 12:00amOriginally posted by: LALeonard
Reply"IsProgramRunning" hangs on WindowsNT
Posted by Legacy on 03/09/1999 12:00amOriginally posted by: jijon
"IsProgramRunning"
function hangs on WindowsNT..
Any soldutions?
Thanks in advance.
Reply