Problem terminating windows processes completely

edit: i have discovered that while this program exhibits this behavior on my machine, this is not true to every machine (one of the six i have personally run it on), and also not to every browser, as firefox does not normally seem to show this problem when set as default browser. most of my users however, will be using IE. I have tried to use code and functions that will allow it to run on the widest range of machines, but from talking to the people, most of their machines are running xp.

I have written software, and one of the functions is to export data to an html file. The user has a button that they can click to view the exported data. This button calls ShellExecuteEx() to open the new file. this new process that opens appears to be a child process to my process.

The Problem: when the 'X' on the opened browser is clicked, or when I remotely terminate the process from my application, the process appears to have terminated (main window disappears), however, in task manager and process explorer, it shows the actual process as still being active. edit: I read somewhere that windows will not unload a process from address space until all handles to that process have been closed, so I tried setting one of the flag members of the SHELLEXECUTEINFO struct so that hProcess would contain a valid process handle, then using that to obtain a process id which i stored to identify the process later. then i closed the handle to the process, hoping that maybe that was the reason... but it didn't work.

Some Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SHELLEXECUTEINFO exInfo;
exInfo.cbSize = sizeof(SHELLEXECUTEINFO);
exInfo.fMask = 0x00000100;
exInfo.hwnd = NULL;
exInfo.lpVerb = "open";
// '.getStatsFn()' is a member function i wrote that returns the filename
exInfo.lpFile = Ini.getStatsFn();
exInfo.lpParameters = NULL;
exInfo.lpDirectory = NULL;
success = (bool)ShellExecuteEx(&exInfo);
// check that ShellExecuteEx returned correctly and that there is not an error code in 'hInstApp'
if(!success || (int)exInfo.hInstApp < 33)
{
    MessageBox(Main.handle, "There may not be a current, valid statistics file:\n"
    "click 'UPDATE' button if you would like to create one...\n"
    "click 'ok' to return to main program.", "Could not display statistics!", MB_OK);
    SendMessage(done.handle, WM_LBUTTONUP, 0, 0);
    return 0;
}


edit: might it have something to do with the fact that it was started as a child process? if I could start it concurrently (such as being a process running under explorer and not my app), do you think that would change the behavior of the browser?

any insight, or ideas would be greatly appreciated, thank you.
Last edited on
If you check the documentation in msdn for ShellExecuteEx there is a member in the structure passed called hProcess that contains the handle to your child process after you launched it.

If your main process is terminated you could terminate the process before you exit using Win32 call TerminateProcess( hProcess, 0 )

hth
Anders.
hello anders43, thank you for your reply. I changed it to use TerminateProcess, but what i found was that since it immediately terminates the process, it does not give the application any time to free all of it's resources or unload dll's. when this occurred, and the user tried to open the same file that had just been open in the browser, it gave an error and said that the file could not be located (as i suspect that the file had not been freed properly). I have since found a couple of ways to "successfully" terminate the application, but since all of them seem to have the same effect, with the process shown as still running, it would be logical to me that the problem is something with how i am opening the file. Thus i have edited my first post to include the code that should have been included when I originally posted the question... the code that actually calls ShellExecuteEx(). Thank you again for your reply, and maybe the code will help diagnose the problem.
Hi, Mal,
as I promised, I played a little with ShellExecuteEx(). Well, I couldn't regenerate the situation you described, I am sorry. I simply utilized the SHELLEXECUTEINFO structure filled with minimum necessary data (much like in your code which I see you published, in the meanwhile) and on my home laptop (Vista Home Premium) clicking the Close ("x") key on the newly created IE7's window led to closing the window plus terminating its process (which disappeared from the Task Manager immediately). So you are obviously rigth that the described behaviour is somewhat "machine specific" and on different computers it might or might not be present. I don't see why it sometimes happens, however, so I cannot help you.
Cheers.
Don't use TerminateProcess() to end programs... it is a last-resort, hatchet-job way of killing the unruly.

I don't know why you are opening it as a DDE process, but in either case, you should refrain from using numbers directly in your code. The <windows.h> header includes everything you need to write something that can be read.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
BOOL ShowUserStats( LPCSTR filename )
  {
  BOOL             result;
  SHELLEXECUTEINFO exInfo;
  exInfo.cbSize       = sizeof( SHELLEXECUTEINFO );
  exInfo.fMask        = SEE_MASK_FLAG_NO_UI
                      | SEE_MASK_NOCLOSEPROCESS;
  exInfo.hwnd         = NULL;
  exInfo.lpVerb       = "open";

  exInfo.lpFile       = filename;
  exInfo.lpParameters = NULL;
  exInfo.lpDirectory  = NULL;

  result = ShellExecuteEx( &exInfo );

  if (!result)
    {
    MessageBox( NULL, "fooey", "caption", MB_OK );
    }

  return result;
  }

Be sure to pay attention to the documentation for these commands.

The SEE_MASK_FLAG_NO_UI flag keeps Windows from displaying its own error dialogue if something goes wrong (since you want to display your own instead).

The SEE_MASK_NOCLOSEPROCESS means to do a non-blocking ShellExecute(). That is to say that the 'filename' document is opened (or fails to open) and control is immediately returned to your program. The handle of the new process is listed in exInfo.hProcess. If the document failed to open, hProcess lists the reason why:

SE_ERR_FNF File not found
SE_ERR_PNF Path not found
SE_ERR_ACCESSDENIED Access denied
SE_ERR_OOM Out of memory
SE_ERR_DLLNOTFOUND Dynamic-link library not found
SE_ERR_SHARE Cannot share open file
SE_ERR_ASSOCINCOMPLETE File association information not complete
SE_ERR_DDETIMEOUT DDE operation timed out
SE_ERR_DDEFAIL DDE operation failed
SE_ERR_DDEBUSY DDE operation busy
SE_ERR_NOASSOC File association not available


The first argument to MessageBox() should be the handle to your application's active window.

The third argument is the caption of the dialogue box, and should be the same as your application's caption.

Hope this helps.

[edit] Oh yeah, notice how you only need to check the success or failure result to determine if something went wrong.
Last edited on
hello Duoas, i very much appreciate your reply. i do have a couple of questions if you have a few minutes to answer.

the first: i googled DDE, and read some information about it, (as i was unfamiliar with the term), however, i don't think i understand what makes the ShellExecuteEx() method a DDE process.

more importantly: how would i do this without DDE, as you implied that would be better?

ps - sorry i didn't reply sooner, i wasn't home this weekend. take care.
Topic archived. No new replies allowed.