Archived

This topic is now archived and is closed to further replies.

Detecting a process

This topic is 5622 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Is there a way to detect whether a process is running or not? In my app, I use ShellExecuteEx() to launch an executable. ShellExecuteEx() returns a handle to a process, which I want to use to find out when the launched app is done running. I have looked at many of the process handling functions, but none of them seem to allow me to see whether a given app is currently running. Any thoughts? -Mike

Share this post


Link to post
Share on other sites
Thanks for the rapid replies! I meant that I need my app (the computer) to detect if a process is currently running. I''m looking into WaitForSingleObject - it may be what I''m looking for. More ideas are welcome.

Share this post


Link to post
Share on other sites
If the process handle returned by ShellExecute is a "pseudo" handle, you can use DuplicateHandle on it to get a "real" handle. You can also get a "real" handle to a spawned process through the process information structure passed in to CreateProcess. CreateProcess also allows for passing i/o handles to the spawned process.

WaitForSingleObject lets you wait on the spawned prog. If it''s a GUI prog and you want to wait for the spawn to initialize, check out WaitForInputIdle.

If you want to check all the currently running processes to see if the program is already running, look into the Toolhelp functions.

Share this post


Link to post
Share on other sites
When I call FormatMessage() after running WaitForSingleObject(), it returns "The handle is invalid." as an error message. Right before running WaitForSingleObject(), ShellExecuteEx() runs. Is the process that ShellExecuteEx considered a "pseudo" handle then?

Also, WaitForSingleObject() talks about waiting for a handle to be in the specified "signaled state". What exactly does it mean to be "signaled"?

-Mike

[edited by - doctorsixstring on July 24, 2002 9:45:08 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by doctorsixstring
When I call FormatMessage() after running WaitForSingleObject(), it returns "The handle is invalid." as an error message. Right before running WaitForSingleObject(), ShellExecuteEx() runs. Is the process that ShellExecuteEx considered a "pseudo" handle then?


I don''t know for certain as I usually use CreateProcess instead of ShellExecuteEx. According to the doc regarding SHELLEXECUTEINFO:
quote:
hProcess
Handle to the newly started application. This member is set on return and is always NULL unless fMask is set to SEE_MASK_NOCLOSEPROCESS. Even if fMask is set to SEE_MASK_NOCLOSEPROCESS, hProcess will be NULL if no process was launched. For example, if a document to be launched is a URL and an instance of Microsoft® Internet Explorer is already running, it will display the document. No new process is launched, and hProcess will be NULL.



quote:
Original post by doctorsixstring
Also, WaitForSingleObject() talks about waiting for a handle to be in the specified "signaled state". What exactly does it mean to be "signaled"?


That means that the object the handle refers to has gained the threads attention and the Wait... function will return WAIT_OBJECT_0+n - that is "success". A nonsignaled object remains in a wait state. There are several different kinds of objects that can be used with the Wait... functions: Change notification, Console input, Event, Job, Mutex, Process, Semaphore, Thread, Waitable timer. Each object signals for different reasons.

In the case of a process, the process signals when it exits, so if you wait on it, the calling thread will remain blocked until either the process exits or the timeout expires. That''s why I mentioned the WaitForInputIdle function as it enables a thread to suspend its execution until the specified process has finished its initialization and is waiting for user input with no input pending. Iirc, WaitForInputIdle does not work with console based programs.

Share this post


Link to post
Share on other sites
Check out the _spawn functions. If you want to spawn a new process and have the calling thread wait until the spawned process is finished (sounds like what you need), you can specify _P_WAIT and the calling thread will be blocked until the spawned process terminates.

[edited by - noparity on July 24, 2002 1:49:39 PM]

Share this post


Link to post
Share on other sites
The _spawn family seems to be what I want. However, it is giving me errors:

When I run the following code:

_spawnvp( _P_WAIT, "Setup.exe", NULL);

I get a "debug assertion failed" error, with the following message: "argv!=NULL". I would assume this means that the system doesn''t like seeing NULL where the argument list should be. However, I don''t need to pass any parameters, so I figured I could set it to NULL.

So what am I doing wrong?

Share this post


Link to post
Share on other sites
GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode) returns STILL_ACTIVE if the process is still running.


bool IsProcRunning(HANDLE hProcess)
{
DWORD dwExitCode;
GetExitCodeProcess(hProcess, &dwExitCode);
return (STILL_ACTIVE == dwExitCode);
}


Regards Mats

Share this post


Link to post
Share on other sites
quote:
Original post by doctorsixstring
So what am I doing wrong?


According to the fine print at MSDN:
quote:

You must pass at least one argument, arg0 or argv[0], to the spawned process. By convention, this argument is the name of the program as you would type it on the command line. A different value does not produce an error.


Try passing the empty string "" instead of NULL and see if that works.

Share this post


Link to post
Share on other sites
If you know the number of arguments you''re going to be passing to the spawned proc (looks like 0 in this case), I would recommend using _spawnlp:


int result = _spawnlp(_P_WAIT, "setup.exe", "setup.exe", NULL);

if (result != 0)
// handle errors...


However, if you really want to use _spawnvp it would look something like this:


char* args[2];
args[0] = "setup.exe";
args[1] = NULL;

int result = _spawnvp( _P_WAIT, args[0], args);



Share this post


Link to post
Share on other sites
Thanks for all the replies, so far. I have been playing around with the _spawn functions and CreateProcess. Here is the code I have been using for each:

//////////
_spawn**()
//////////

  
_spawnlp(_P_WAIT, strSetupDir, strSetupDir, NULL);


//////////
CreateProcess()
//////////

  
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);

CreateProcess(strFilenameWithPath,NULL,NULL,NULL,FALSE,0,NULL, NULL, &si, &pi);

DWORD dwExitCode = STILL_ACTIVE;

while(dwExitCode == STILL_ACTIVE)
GetExitCodeProcess( pi.hProcess, &dwExitCode );


Both methods of launching the new program seem to work at first, but my program only seems to wait until the new program initializes before it resumes.

I should probably go into more detail about the program I am launching. My app is basically a simple launcher to choose between multiple setup programs. Depending upon the user''s selection, the appropriate Setup.exe file is launched. All of the setup files were created with InstallShield. I was thinking that maybe an InstallShield app launches another file, thus causing my original program to think that the setup is complete.

I hope I explained this well enough...
-Mike

Share this post


Link to post
Share on other sites
It seems like InstallShield setup programs are actually multiple executables, with the primary file "setup.exe" launching another setup program. In this case, my program is correct when it sees that "setup.exe" has quit. Is there any way to track processes created by processes that my program creates? I don''t have much hope, but if anyone has a solution, I would be very happy.

-Mike

Share this post


Link to post
Share on other sites
I can''t speak much to the spawn code. Here''s my take on the CreateProcess code.


  
DWORD ExecuteCommand(char *strFilenameWithPath, int cmdShow)
{
int processStarted;
DWORD dwExitCode = STILL_ACTIVE;

STARTUPINFO si;
PROCESS_INFORMATION procinfo; // changed from pi due to html formatting


memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = cmdShow;

processStarted = CreateProcess(strFilenameWithPath,NULL,NULL,NULL,FALSE,0,NULL, NULL, &si, &procinfo);
if ( processStarted == 0 ) {
// error!

}

// while(dwExitCode == STILL_ACTIVE)

// this while loop is not the way to do it


WaitForSingleObject(procinfo.hProcess, INFINITE);

GetExitCodeProcess( procinfo.hProcess, &dwExitCode );

return dwExitCode;
}

quote:
Original post by doctorsixstring
I was thinking that maybe an InstallShield app launches another file, thus causing my original program to think that the setup is complete.



That might well be the case. Head over to sysinternals.com and grab a copy of ProcExplorer, it will show you if the InstallShield spawns any children or not.

Share this post


Link to post
Share on other sites
quote:
Original post by doctorsixstring
It seems like InstallShield setup programs are actually multiple executables, with the primary file "setup.exe" launching another setup program. In this case, my program is correct when it sees that "setup.exe" has quit. Is there any way to track processes created by processes that my program creates? I don''t have much hope, but if anyone has a solution, I would be very happy.

-Mike


Take a look at the Toolhelp Api''s - and if you need your prog to work on NT4 then also look at the PSAPI.

Share this post


Link to post
Share on other sites