HPROCESS & ShellExecute()

Posted on 2003-02-21
Medium Priority
Last Modified: 2013-12-03
I need to use ShellExecute() (or ShellExecuteEx()) to run the app associated with a file. So far no problem....

However, I then need to wait for the application launched by ShellExecute(Ex) to end. So I need the process handle to use with WaitForSingleObject(). And I can't find a reliable way to get the process handle (or process id).

Every technique I looked at has a problem:
1. ShellExecuteEx doesn't always return the HPROCESS. e.g. if Word is already running before calling ShellExecuteEx() the HPROCESS returned is NULL.
2. Using a kernel mode driver to access the native NT object manager requires that the user has service install priveleges - which won't always be the case (this is the technique used by HandleEx, www.sysinternals.com , and it's clones on www.codeguru.com). It also means relying on undocumented functionality in NT. :-(

Can anyone help?

(My target OS is NT4, Win2K & XP)
Question by:abancroft
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
  • 2
  • +1

Expert Comment

ID: 7998218
Hi abancroft!

Below sample code about this :


ZeroMemory(&sei, sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
sei.lpFile = (LPCSTR)szPath;
sei.lpParameters = (LPCSTR)szParams;
sei.nShow = SW_SHOW;


if (sei.hProcess)
    WaitForSingleObject(sei.hProcess, INFINITE);
    //do there what you need

LVL 49

Expert Comment

ID: 7998423
The documentation says that Avdey's code will fail for exactly the reason that abancroft cited.

My only idea is this:

Call FindExecutable(...) to obtain the name of the program that should be used to open the target data file (eg, obtain "d:\path\winword.exe" when passing in "myfile.doc").  Then use CreateProcess(...) to open that program, passing in the name of the file as the command-line parameter.

Perhaps it would be worth checking this out:  The HINSTANCE might have an undocumented meaning in this case where DDE was used to open the document.  Try setting the SEE_MASK_FLAG_DDEWAIT flag and seeing if there is any hope there.

-- Dan
LVL 20

Expert Comment

ID: 7998751
Perhaps FindExecutable + CreateProcess works better? Perhaps that works without DDE...
Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

LVL 49

Expert Comment

ID: 7999998
You could play around with the START command of a DOS box.  
   START /WAIT MyProg.Exe
is said to wait until MyProg.Exe (or MyFile.Doc?) is finished.  Maybe the programmers of the START command have found an answer to your problem.

Also, I don't think you can ever be 100% certain.  For instance, some programs limit themsleves to running just one copy.  Thy set a system global Mutex and early on in the startup they check to see if it is set, and if so, they post a message to the other (original) program telling it to come to the front and to open any file passed as a command-line parm.  In this case, the program that was launched would quit right away, so the desired processing (that is, taking action on the filename passed as a parameter) would not be finished.

There may be other angles of attack.  Please answer these questions:
1) Why do you wish to know when the executed program finishes?  
2) What is your actual goal?.

-- Dan

Expert Comment

ID: 8002073
Hi guys !
What can i said ? I check this code under NT4.0 (launch *.bmp file, i.e. szPath == "x:\path\filename.bmp", szParams == "") and it's work fine.
LVL 49

Expert Comment

ID: 8002126
Try that with a WORD file (myfile.doc) when MS WORD is already running with another document open.  That is the question posted by abancroft.
-- Dan

Author Comment

ID: 8009175
Wow - lots of activity over a weekend! (maybe that's how to rack up expert points....:-)

Avdey - ShellExecuteEx() will not work. I describe one situation where the hProcess will always be NULL in the question.

DanRollins - I wasn't aware of the FindExecutable() API, despite looking! (sometimes it's difficult to find what you're looking for in MSDN). It may help somewhat, but as you say some programs limit themselves to one instance (the program I work on does this using the technique you describe).

In detail, here's what I'm trying to do:
1. In a database, the user can store files.
2. From the app, the user can double click on a 'file' & it is saved to a temp file & opened using the app associated with.
3. Now the user can edit the file - but when they save it, it is saved to the temp file, not the DB.

So far, so good. But it'd be nice if we could update the file in the DB when the user saves to the temp file (i.e. keep them in sync). No problem, just use FindFirstChangeNotification/FindNextChangeNotification.

But I need to know when the user has finished editing the file, so I can shut down my app and delete the temp file. To do this, I thought I'd get the process handle of the editing app & use WaitForSingleObject.

But it turns out that 'get the process handle' is a difficult task.
LVL 49

Accepted Solution

DanRollins earned 800 total points
ID: 8010268
Thanks for the complete description.

The important part -- getting the updates into the database -- is done.  I think you have the 96% and are working on the last 4%.   Maybe you can squeeze out another 2% by using FindExecutable and EnumProcess and then learn when that program closes.  When it does, you can know to cleanup the temp.

Then what's left is just a few programs that the user saved but left Word or Excel open for some reason.   You can get 1% more by handling WM_QUERYENDSESSION (indicate Windows is about to restart).

Now the last 1%:  
Use a recognizable naming scheme (such as  
for your temp files.  When your program starts up, go through and delete all such files -- they were left over from the last time that your program ran and the system crashed.

-- Dan

Author Comment

ID: 8011896
FindExecutable and EnumProcess work very well:
1. Record original file attributes in a WIN32_FIND_DATA.
2. Figure out the EXE using FindExecutable().
3. Launch using ShellExecute()
4. Get the process handle(s) using EnumProcess/EnumProcessModules/GetModuleFileNameEx.
5. Wait for process(es) to finish
6. Get new file attributes in a WIN32_FIND_DATA
7. Compare both WIN32_FIND_DATA structs to see if file has changed.

This works for straight app launching (e.g. notepad), DDE programs (e.g. Word, IE) and singleton apps (e.g. Outlook).

Thx Dan.

Featured Post

Enroll in August's Course of the Month

August's CompTIA IT Fundamentals course includes 19 hours of basic computer principle modules and prepares you for the certification exam. It's free for Premium Members, Team Accounts, and Qualified Experts!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes a technique for converting RTF (Rich Text Format) data to HTML and provides C++ source that does it all in just a few lines of code. Although RTF is coming to be considered a "legacy" format, it is still in common use... po…
What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question