Feststellen ob Programm läuft?

Hallo,

aus einer MFC-Anwendung starte ich mit der Funktion WinExec ein anderes Programm. Nun muesste ich irgendwie abfragen, ob dieses neu gestartete Programm noch läuft. Besser noch wäre es, wenn das Programm geschlossen wird, meine MFC-Anwendung eine Nachricht bekommt, die dann behandelt werden kann.

Kann mir jemand sagen, wie das geht?

Danke, Robert

Hallo Robert!

Ich kenne keine Methode, mit der man sich Messages über die Terminierung eines Prozesses schicken lassen kann, was nicht heißen soll, dass es diesen vielleicht auch nicht gibt.

Ich schlage jedoch einen anderen Weg vor. Polling ist das Stichwort, welches dich zum Ziel leiten soll. Du fragst einfach ständig mit der Funktion

HWND FindWindow(
LPCTSTR lpClassName, // pointer to class name
LPCTSTR lpWindowName // pointer to window name
);

ab, ob dieses Fenster noch existiert:

if (FindWindow („DieseApp“, NULL))
{
//existiert
}
else
{
//existiert nicht
}

Eine Möglichkeit wäre da ein Timer oder einfach eine Message-Loop um deine Anwendung nicht zu erschöpfen:

_MSG message;

while (nochImmerAbfragenWollen)
{
if(::stuck_out_tongue:eekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
::TranslateMessage(&message);
::smiley:ispatchMessage(&message);
}

if (FindWindow(„DieseApp“, NULL))
{
//existiert noch
}
else
{
//existiert nicht mehr
}
}_

Alle genauen Parameterbeschreibungen findest in der MSDN - wo sonst!

Hoffentlich konnte ich helfen,
KoRn!

Hallo KoRn,

Ich schlage jedoch einen anderen Weg vor. Polling ist das
Stichwort, welches dich zum Ziel leiten soll.

Vielen Dank für die Hilfe. Hast mir jetzt schon das dritte Mal aus der Patsche geholfen :wink:

Gruß, Robert

Da fällt mir noch was ein :smile:

Die Lösung funktioniert zwar einwandfrei, allerdings ist die Anwendung, die ich aus meinem Programm starte, nicht immer dieselbe. Hintergrund: habe mir was geschrieben, das auf neue Mails überprüft und dann bei Doppelklick den Mailclient startet, den man einstellen kann. Und jetzt hat ja nicht jeder Outlook oder Netscape, d.h. wenn ich mit FindWindow arbeite müsste ich genau den Fensternamen kennen, der durch WinExec aufgerufen wurde.

Hast Du 'ne Idee? :smile:

Danke, Robert

Hallo Robert.

Wie wär’s, wenn Du statt WinExec die Funktion CreateProcess nimmst? MSDN sagt zu WinExec:

" Note This function is provided only for compatibility with 16-bit Windows. Win32-based applications should use the CreateProcess function. The CreateProcess function is used to run a new program. The WinExec and LoadModule functions are still available, but they are implemented as calls to CreateProcess."

Zu den Parametern von CreateProcess gehört u.a. auch eine PROCESS_INFORMATION-Struktur:

typedef struct \_PROCESS\_INFORMATION { 
 HANDLE hProcess; 
 HANDLE hThread; 
 DWORD dwProcessId; 
 DWORD dwThreadId; 
} PROCESS\_INFORMATION; 

Mit GetExitCodeProcess(…) kriegst Du z.B. den Wert STILL_ACTIVE zurück, solange der Prozeß läuft. Ansonsten kannst du mit WaitForSingleObject(…) und den verwandten Funktionen auf die Beendigung des Threads warten bzw. Abfragen, ob er noch läuft. Du kannst Dir ja auch WM_TIMER-Nachrichten schicken lassen und dann jedesmal nachschauen, ob der Prozeß noch läuft. Auf diese Art kriegst Du die Abfrage in Deiner Nachrichtenschleife unter.

Eine Möglichkeit, sich bei Prozeßende eine Nachricht schicken zu lassen, kenne ich Windows-seitig nicht. Wenn die Vorteile extrem groß wären, würde ich mir überlegen ob ein Stub-Programm sinnvoll ist. Damit meine ich einen Programmkrümel, den Du dann meinswegen auch mit WinExec starten kannst und der seinerseits den gewünschten Prozeß startet. Anschließend tut er nix als z.B. alle ein oder zwei oder drei Sekunden auf die eine oder andere Art zu prüfen, ob der Prozeß noch läuft. Dazwischen schläft das Stub-Programm und kostet keine CPU-Zeit. Wenn es feststellt, daß der Prozeß beendet ist, schickt es eine selbstdefinierte Nachricht an Dein eigentliches Programm und beendet sich. Aber das muß sich dann wohl wirklich schon lohnen.

Gruß, Ralf

Hallo Robert!

Auf ins 4te-Mal. Ich habe ganze 15 Minuten gebraucht, bis ich endlich dein Problem, so glaube ich, an der Nase gepackt habe! Du kannst die Funktion CreateProcess

BOOL CreateProcess(
LPCTSTR lpApplicationName,
// pointer to name of executable module
LPTSTR lpCommandLine, // pointer to command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // process security attributes
LPSECURITY_ATTRIBUTES lpThreadAttributes, // thread security attributes
BOOL bInheritHandles, // handle inheritance flag
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // pointer to new environment block
LPCTSTR lpCurrentDirectory, // pointer to current directory name
LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO
LPPROCESS_INFORMATION lpProcessInformation // pointer to PROCESS_INFORMATION
);

ja eh wie WinExec (hat eigentlich Ralf Klaus schon geschrieben) verwenden. In dieser Funktion wird der Identifier des Process über die Übergabeparameter zurückgegeben:

MSDN:

The process is assigned a 32-bit process identifier. The identifier is valid until the process terminates. It can be used to identify the process, or specified in the OpenProcess function to open a handle to the process. The initial thread in the process is also assigned a 32-bit thread identifier. The identifier is valid until the thread terminates and can be used to uniquely identify the thread within the system. These identifiers are returned in the PROCESS_INFORMATION structure.

Über diesen Identifier kannst du dann mit OpenProcess versuchen dieses Programm zu öffnen, falls es noch nicht terminiert wurde!

Auf gut C++:

_CreateProcess („c:\MainMailProg.exe“, …, …, lpProcessInformation, …);

MailProcessID = lpProcessInformation->dwProcessId;

if (OpenProcess(MailProcessID))
{
//Process läuft noch
}
else
{
//ProcessID existiert nicht --> Process schon terminiert.
}_

Ich hoffe wiedermal auf ein erfolgreiches 5te-Mal,
KoRn!

Auf ins 4te-Mal…

Hast was gut bei mir :wink:

Ich habe in den nächsten Tagen zwar keine Zeit das auszuprobieren, allerdings vertraue ich voll auf Deine Kenntnisse :smile:

Vielen Dank nochmal für Deine Hilfe & Geduld, Robert