Help needed to check whether another program is running

Help needed to check whether another program is running

Does anyone have an example of how to check whether another program is running from within Fortran?

I think the WinAPI function is GetProcesses, but can't find anything else.

What I'm trying to do is to run multiple copies of a program by creating a commnad file which uses the START command, execute it using SYSTEMQQ, and then once all copies have completed, collate all the results.

Thanks,

David

 

14 Beiträge / 0 neu
Letzter Beitrag
Nähere Informationen zur Compiler-Optimierung finden Sie in unserem Optimierungshinweis.

If you can use the Windows API and your Fortran program directly launches the other programs it is easy enough - you can wait on the process handles returned from a series of CreateProcess calls using WaitForMultipleObjects.  This is much more simple and robust than querying the list of active processes (see here for a C example) and relying on that.

If you were back at a design stage for this the you could perhaps map each child process across to a Fortran image, and use coarrays.  I imagine that might be a bit tricky to retrofit though.

You can use the Process Status API (module PSAPI) to do this. Look at the ProcessStatus sample we provide. This one gets memory usage for each process, but you can use GetProcessImageFileName to get the executable file name instead.

Steve - Intel Developer Support

Steve,

For some reason, the ProcessStatus example does not list any of my running Fortran programs. But if I lookup the PID using TaskManager and put that into my adapted version of ProcessStatus, it correctly returns the file name.  Why doesn't the process list in the example get all of the running process PID's?

Thanks,

David

Interesting - when I try the sample it does show a Fortran program I have run separately. Please attach your modified version and I'll try it out.

I've attached my version. Instead of GetProcessImageFIleName, which returns the filename in \device\... format, I used QueryFullProcessImageName (available in Vista and later.) This isn't in module KERNEL32 so I declared it independently.

Anlagen: 

AnhangGröße
Herunterladen processstatus.f905.11 KB
Steve - Intel Developer Support

Here is my version.

It appears that when I call my program from inside ProcessStatus, then the processID cannot be obtained. If my program is still running (e.g. from a previous execution of ProcessStatus), then it detects the processID.  I thought at first that checking the ProcessID's was happening so fast that they were all checked before the other program could start, but this is definitely not the problem.

I have tried running this both from within VS and directly from Windows Explorer, with the same results.

Thanks

David

Anlagen: 

AnhangGröße
Herunterladen processstatus.f901.79 KB

Perhaps I have misunderstood your intent - but it appears that you get the list of running processes (via EnumProcesses) before you have created your process of interest (via SYSTEMQQ).

Thanks, Ian.  I guess if the logic is wrong, the program won't work! :-(

David

In the absence of mitigating reasons to the contrary, I still think you'd be far better off directly managing the processes yourself, rather than this indirect approach of watching the filename.

The attached was something I put together a while ago when fooling around looking at options around tracking child process success (I can't remember what the background was).  Most of it is not relevant here - but if you have a look at the check_return_code internal procedure you'll see a call to CreateProcess and WaitForSingleObject.  Pop the CreateProcess in a loop, make the relevant arguments arrays, and change the Wait API to WaitForMultipleObjects, and you're done.  Scalable (wait for thousands of kids if you want), robust, CPU friendly (no polling)...

(Is the issue the use of an intermediate batch file to launch the child jobs?)

Anlagen: 

AnhangGröße
Herunterladen simpleloader.f9019.69 KB

Thanks, Ian.  I'll look at it tomorrow.

I looked at using the batch file to run the child jobs becuase the START command enables me to sequentially start multiple copies which will run concurrently.

I started looking at parallelizing my program, but due to the data arrangement it appears that this would be a major undertaking, not just in restructuring how the program works, but in testing.  As a major use of the program involves running mutliple independent cases, the next best solution would be to run multiple copies of the program (albeit with memory and load time implications). Hence the solution I am looking at.

You suggest launching the program using create process - can this include command line arguments, because if I am to do this without any rewriting my application, I would need to be able to specify some, particularly the input file name.

Thanks,

David

Yep - it allows a command line (it has to - it, or its siblings, are the relatively low level API's that any Win32 process gets created through).  You may need to quote parts of the command line if it contains things that might confuse the language runtime for the child process when it goes about splitting that command line up into individual arguments.  Depending on how you specify the program to be executed, you may also need to quote that if its path or name contains spaces.  An example of the logic that I think (which is materially different to "I know"!) is required for the command line (in particular) is in main_worker, see the msdn page for CreateProcess for more info.

What CreateProcess won't do on its own is things like command line redirection (program.exe > output.txt), or execution of programs that are not exe's (e.g. it won't execute batch files or other scripts).  A simple workaround for that is to use cmd.exe with appropriate command line arguments as an intermediate child process.

(Not relevant to your use case, but what I attached up thread has silliness in the check_event internal procedure with remnant crap in the  assignment to success_flag.)

Ian,

How do I define the proc_info variable as an array and then get it to work with WaitforMultipleObjects?

I used

TYPE (T_PROCESS_INFORMATION),DIMENSION(nCount) :: proc_info

and

proc_info(iarg) as the argument in the CreateProcess call, but

wait_result = WaitForMultipleObjects(nCount, proc_info%hProcess, TRUE, INFINITE)

gets me stumped.

How do I pass the whole array of pointers to WaitForMultipleObjects?

As shown above, I get a compile error:

Error 1  error #6634: The shape matching rules of actual arguments and dummy arguments have been violated.   [HPROCESS] C:\Open\kwc54dw\Dev\Multiloader\multiloader.f90 108

Thanks,

David

I think  WaitForMultipleObjects wants a single pointer (address) for a contiguous array of handles. I think (I am not certain) you need to create an array in type Integer(handle) e.g. Integer(handle) :: fred(ncount) and then asign fred= proc_info%hProcess and then pass loc(fred)

app4619 has it.  Simple example attached.

It is a shame that the IFWIN interface wasn't (also) declared to take an assumed size integer array.

(I see I lied a bit about the thousands of child processes too - the limit is 64 and then you have to start playing games waiting on child threads that are waiting on objects.)

Anlagen: 

AnhangGröße
Herunterladen multipleloader.f902.31 KB

Kommentar hinterlassen

Bitte anmelden, um einen Kommentar hinzuzufügen. Sie sind noch nicht Mitglied? Jetzt teilnehmen