1

I want to "listen" some other application and decide what to do when it has been terminated.

How?

Edit: The two programs are run on same computer, and i want to know when i close the other program. And then do action in the other program. I cant modify the other program code. I may or may not start the app B from app A. I could identify the app B by its full path to the exe.

Newbie
  • 1,143
  • 5
  • 20
  • 30
  • 1
    You should define more exactly which relationship has your application A with the application B which you want to monitor for the termination. Do you start the application B from the application A with respect of `CreateProcess` for example? If not, then "How you identify the application B: by filename, by windows title and so on?". Is application B is a GUI application, a console application or a windows service for example? I can continue... You current question can be interpret in too many ways. – Oleg Nov 22 '10 at 13:00

4 Answers4

5

As Abyx wrote, WaitForSingleObject (or possibly WaitForMulipleObjects) is the API function you need.

  1. Create an event
  2. Start a (worker) thread
  3. Pass the event handle to the thread -> HANDLE1
  4. Get handle for the process to be watched. See How can I get a process handle by its name in C++? -> HANDLE2
  5. In your thread function call WaitForMulipleObjects and wait for the two handles.
  6. If HANDLE2 fires, do whatever action you want... and possibly terminate the thread.
  7. If HANDLE1 fires, leave the thread. This is for a graceful termination of your application: Before exiting the main (GUI) thread you set the event.
Community
  • 1
  • 1
ur.
  • 2,890
  • 1
  • 18
  • 21
  • i have no clue how to do steps 1-4, what do you mean by "fires" in this case? by 7 you mean if my main program quits, i need to quit the thread i created? doesnt windows handle this automatically? – Newbie Nov 22 '10 at 14:25
  • What I mean with "fires" is a change from nonsignaled state to signaled state. See MSDN, "SetEvent" http://msdn.microsoft.com/en-us/library/ms686211(VS.85).aspx. – ur. Nov 22 '10 at 14:35
  • Yes, Windows will terminate your thread but you might have to do some cleanup in your thread (e.g. close a logfile). It's a matter of style: If you create a thread you should have a means of terminate it. – ur. Nov 22 '10 at 14:37
  • +1 for completeness. The remote process handle will become signalled when that process exits. – Steve Townsend Nov 22 '10 at 15:04
  • Also note that the `Wait*` APIs will block and that's why you need a new thread for this monitoring. Polling (the other choice) is not a good way to handle this when there is an event-driven alternative as described here. – Steve Townsend Nov 22 '10 at 15:57
  • This seems overkill, what's wrong with waiting on the process handle? – David Heffernan Nov 23 '10 at 19:09
  • @David: As always: It depends... :-) We don't know the whole context of the OPs application. But actually it's another 10 lines of code from "minimalistic" to "overkill". If you don't have an extra thread: How do you close the application A (without closing application B)? Also: If there's a message loop it's blocked without another thread. – ur. Nov 23 '10 at 19:58
4

WaitForSingleObject(hProcess, INFINITE);

Abyx
  • 12,345
  • 5
  • 44
  • 76
1

If you start yourself, the process which termination you want wait for, for example with respect of the CreateProcess, the waiting for the process end is very simple

WaitForSingleObject(pi.hProcess, INFINITE);

If the process, which termination you want wait for, is started before you should find the process id dwProcessId of the process and then do following

HANDLE hProcess = OpenProcess (SYNCHRONIZE, FALSE, dwProcessId);
WaitForSingleObject(hProcess, INFINITE);

The searching of the process id can be implemented in different ways depend on which information you know about the process and the knowledge how many instances of the process can be running simultaneously.

For example if you know the filename of the process which is currently running you can use EnumProcesses, OpenProcess and GetProcessImageFileName. Here is the corresponding code in a simplified form:

#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <Psapi.h>
#include <shlwapi.h>

#pragma comment (lib, "Psapi.lib")
#pragma comment (lib, "shlwapi.lib")

int _tmain (int argc, LPCTSTR argv[])
{
    DWORD arProcessIds[1024], cbNeeded, i, dwStatus;
    HANDLE hProcess = NULL;
    LPCTSTR pszProcessName = NULL;

    if (argc != 2) {
        _tprintf (TEXT("USAGE:\n")
                  TEXT("    \"%s\" ExeName\n\n")
                  TEXT("Examples:\n")
                  TEXT("    \"%s\" TaskMgr.exe\n"),
                  argv[0], argv[0]);
        return 1;   // error
    }
    pszProcessName = argv[1];

    if (!EnumProcesses (arProcessIds, sizeof(arProcessIds), &cbNeeded)) {
        // here shold be allocated array dynamically
        return 1;   // error
    }
    for (i = 0; i < cbNeeded/sizeof(DWORD); i++ ) {
        if (arProcessIds[i] != 0) {
            TCHAR szFileName[MAX_PATH];
            hProcess = OpenProcess (PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, arProcessIds[i]);
            if (hProcess != NULL) {
                dwStatus = GetProcessImageFileName (hProcess, szFileName, sizeof(szFileName)/sizeof(TCHAR));
                if (dwStatus > 0 ) {
                    LPCTSTR pszFileName = PathFindFileName (szFileName);
                    //_tprintf(TEXT("Process: %s\n"),szFileName);
                    if (StrCmpI(pszFileName, pszProcessName) == 0) {
                        break;
                    }
                }
                CloseHandle (hProcess);
                hProcess = NULL;
            }
        }
    }
    //hProcess = OpenProcess (SYNCHRONIZE, FALSE, dwProcessId);
    if (hProcess == NULL) {
        _tprintf(TEXT("The process \"%s\" is not found.\n"), pszProcessName);
        return 1;
    }

    _tprintf(TEXT("Start waiting for the end of the process %s\n"), pszProcessName);
    WaitForSingleObject(hProcess, INFINITE);
    _tprintf(TEXT("The process is terminated"));
    CloseHandle (hProcess);

    return 0;
}
Oleg
  • 220,925
  • 34
  • 403
  • 798
0

you can just get the process list from OS in intervals you want and take appropriate action