prüfen, ob Programm läuft, bzw. beendet wurde [Erledigt]

Fragen rund um diverse Windows-Versionen, ihr Verhalten unter Xbase++ und den Umgang mit der API

Moderator: Moderatoren

Antworten
stevie
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 417
Registriert: Mo, 17. Sep 2007 18:20
Wohnort: Senftenberg
Kontaktdaten:

prüfen, ob Programm läuft, bzw. beendet wurde [Erledigt]

Beitrag von stevie »

Hi,
also ich habe Dokumente, die mit ihren Standardprogrammen per Runshell geöffnet werden.
Nun möchte ich aber, sobald das Programm geschlossen wurde, in meinem Programm einen Speichervorgang starten, also Änderungsdatum abspeichern.
Dafür wollte ich nun einen eigen Thread starten, der eben ständig prüft, ob die Exe schon beendet wurde.
Dabei habe ich eine Funktion getTasklist, die mir alle alle Handles Namen der offenen Fenster zurückgibt.
ich will einfach im Thread ständig nach der Exe in der Taskliste suchen und wenn sie nicht mehr gefunden wird, den Speichervorgang einleiten.
Nun wollte ich wissen, wie man aus einem Fensterhandle den Namen der "Exe" herausfindet?

Vielen Dank schon mal
Zuletzt geändert von stevie am Mo, 18. Mai 2009 11:27, insgesamt 3-mal geändert.
Viele Grüße
Stevie
Benutzeravatar
Lewi
1000 working lines a day
1000 working lines a day
Beiträge: 830
Registriert: Di, 07. Feb 2006 14:10
Wohnort: Hamburg
Danksagung erhalten: 2 Mal

Re: prüfen, ob Programm läuft, bzw. beendet wurde

Beitrag von Lewi »

Hallo Steve,
Wenn Du die Standard-Anwendungen kennst, mit denen die jeweiligen Dokumente aufgerufen werden
helfen Dir nachfolgende Funktionen weiter.
Solltest Du die jeweiligen Programme nicht kennen, die je Dokumententyp betriebssystemseitig eingestellt sind, lassen sich die Anwendungen jedoch über das Win-Api ermitteln.

Code: Alles auswählen


If CheckisProgRunning( "winword.exe")
  .... do this
else
  .. do this
endif


Func CheckIsProgRunning( cExe, nPid )
 Local lRet
 Local lTerminate := .F
 lRet := CheckProzessTask(cExe,nPid, lTerminate)
Return ( lRet ) 


DLLFUNCTION EnumProcesses(@lpidProcess,cb,@cbNeeded)                        USING STDCALL FROM PSAPI.DLL
DLLFUNCTION OpenProcess(dwDesiredAccess,bInheritHandle,dwProcessId)         USING STDCALL FROM KERNEL32.DLL
DLLFUNCTION EnumProcessModules(hProcess,@lphModule,cb,@lpcbNeeded)          USING STDCALL FROM PSAPI.DLL
DLLFUNCTION GetModuleBaseNameA(hProcess,hModule,@lpBaseName,nSize)          USING STDCALL FROM PSAPI.DLL
DLLFUNCTION TerminateProcess(hProcess, uExitCode)                           USING STDCALL FROM KERNEL32.DLL
DLLFUNCTION CloseHandle(hObject)                                            USING STDCALL FROM KERNEL32.DLL

#DEFINE PROCESS_QUERY_INFORMATION  1024
#DEFINE PROCESS_VM_READ            16
#define STANDARD_RIGHTS_REQUIRED   (0x000F0000)
#define SYNCHRONIZE                (0x00100000)
#define PROCESS_ALL_ACCESS         (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)
#define PROCESS_TERMINATE          (0x0001)

/* Funktion zum Feststellen, ob ein Prozess (Programm) aktiv ist
/* gibt .T. zurück, falls ja
/* wenn lTerminate := .T., werden alle Instanzen des Prozesses gelöscht
/* Diese Funktion funktioniert auch, wenn ein Prozess kein Fenster hat und nicht auf der Taskleiste zu sehen ist 
Function CheckProzessTask(cExe,nPidId, lTerminate)
   Local aProcesses  := space(10240)
   Local aModules    := space(4*10)
   Local cbNeeded    := 0
   Local cbNeeded2   := 0
   LOcal cname       := space(64)
   Local lIsKill     := .F.
   Local nPid
   Local nProcHandle
   Local i,nMax
   LOcal hmod
   Local xRet
   Local lStillRunning := FALSE 

   EnumProcesses( @aProcesses, LEN(aProcesses) , @cbNeeded )
   nMax := len(trim(aProcesses))/4
   for i:= 1 to nMax
      nPid := Bin2U(substr(aProcesses,1+((i-1)*4),4))
      if nPidId==NIL .or. (nPIdId==nPid)
         nProcHandle  := OpenProcess( PROCESS_QUERY_INFORMATION + PROCESS_VM_READ ,0, nPid )
         if nProcHandle > 0
            if  EnumProcessModules( nProcHandle, @aModules,len(aModules)/4, @cbNeeded2) != 0
               cName := space(128)
               GetModuleBaseNameA( nProcHandle,bin2u(substr(aModules,1,4)),@cName,len(cName))
               cName := strtran(cname,chr(0),"")
               CloseHandle(nProcHandle)
               if upper(trim(cName)) == upper(cExe)
                  IF lTerminate
                     nProcHandle := OpenProcess(1,0,nPId)
                     xRet := TerminateProcess(nProcHandle,1)
                     CloseHandle(nProcHandle)
                     if xRet <> 0
                        sleep(100)
                        lIsKill := .T.
                     endif
                  ELSE
                     lStillRunninng := TRUE 
                     EXIT
                  ENDIF
               endif
            endif
         endif
      endif
   next
RETURN ( lStillRunning )

stevie
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 417
Registriert: Mo, 17. Sep 2007 18:20
Wohnort: Senftenberg
Kontaktdaten:

Re: prüfen, ob Programm läuft, bzw. beendet wurde

Beitrag von stevie »

Also theroetisch geht die Funktion ja einwandfrei. Das Problem ist aber, dass der Stringvergleich immer schief geht. Ich übergebe einen String "WINWORD.EXE", der bekanntlich 11 Zeichen hat, was auch in der Funktion rauskommt, aber mein übergebener String wird grundsätzlich mit Länge 12 verglichen, wodurch cName == cExe fehlschlägt, trotz des absolut gleichen Textes.
Viele Grüße
Stevie
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16509
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: prüfen, ob Programm läuft, bzw. beendet wurde

Beitrag von Martin Altmann »

Hallo Stevie,
könnte das was mit der Stringterminierung "\0" bei der Rückgabe der API-Funktion zu tun haben?
Das strtran( ...chr(0), "" ) hast Du gesehen und übernommen?
Genauso wie das trim(..) vor dem endgültigen Vergleich?

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Lewi
1000 working lines a day
1000 working lines a day
Beiträge: 830
Registriert: Di, 07. Feb 2006 14:10
Wohnort: Hamburg
Danksagung erhalten: 2 Mal

Re: prüfen, ob Programm läuft, bzw. beendet wurde

Beitrag von Lewi »

Wenn Du den Funktionscode 1:1 übernimmst, dann sollte das Problem nicht auftreten. Ich habe die Funktion in Live-Anwendungen ohne das ich bisher irgendwelche User-Fehlermeldungen bekommen habe.
stevie
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 417
Registriert: Mo, 17. Sep 2007 18:20
Wohnort: Senftenberg
Kontaktdaten:

Re: prüfen, ob Programm läuft, bzw. beendet wurde

Beitrag von stevie »

also ich habe jetzt die Funktion c_trim aus Phils' Ide benutzt, um den String an die Funktion zu übergeben, damit klappte es dann.
Viele Grüße
Stevie
Antworten