Programm bereits gestartet ?

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

Moderator: Moderatoren

Antworten
Benutzeravatar
Rolf Ramacher
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1930
Registriert: Do, 09. Nov 2006 10:33
Wohnort: Bergheim
Danksagung erhalten: 3 Mal
Kontaktdaten:

Programm bereits gestartet ?

Beitrag von Rolf Ramacher »

Hallo zusammen,

ich erhalten von einem Kunden eine Anfrage, - kann geprüft werden, ob das Programm bereits gestartet ist und wenn das Programm aus der Taskleiste holen und wieder auf den Vordergrund bringen ?

Hat dies jemand schon gemacht ?
Gruß Rolf

Mitglied der Gruppe XUG-Cologne
www.xug-cologne.de
Benutzeravatar
Herbert
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 1991
Registriert: Do, 14. Aug 2008 0:22
Wohnort: Gmunden am Traunsee, Österreich
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: Programm bereits gestartet ?

Beitrag von Herbert »

Rolf

Ob es schon läuft:

Code: Alles auswählen

#define MUTEX_ALL_ACCESS  2031617

PROCEDURE AppSys()
LOCAL cMutex:=Upper(AppName())+Chr(0)
LOCAL nH:=DllCall("KERNEL32.DLL", DLL_STDCALL,;
                  "OpenMutexA", MUTEX_ALL_ACCESS, 0, cMutex)
IF nH=0
  nH:=DllCall("KERNEL32.DLL",DLL_STDCALL,"CreateMutexA",0,0,cMutex)
ELSE
  MsgBox("Das Programm wird bereits ausgeführt!",cMutex)
  QUIT
ENDIF
DllCall("KERNEL32.DLL",DLL_STDCALL,"ReleaseMutex",nH)
So klappts auch in Windows 7
Das Hervorholen mach ich nicht, da das Ding ja in der Taskleiste steht.
Grüsse Herbert
Immer in Bewegung...
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: Programm bereits gestartet ?

Beitrag von Jan »

OK, etwas länger, aber das macht beides: Festellen ob das Programm schon läuft, und das laufende Programm nach vorne holen. Im Programm setze ich das so ein:

Code: Alles auswählen

IF IsAppRunnung("Test.exe", NIL, .t.)
   Return NIL
ENDIF
Und das eigentliche Programm:

Code: Alles auswählen

#DEFINE SW_RESTORE 9

DLLFUNCTION ShowWindow(nWinHandle,nCmdShow) USING STDCALL FROM USER32.DLL
DLLFUNCTION BringWindowToTop(nWinHandle) USING STDCALL FROM USER32.DLL
DLLFUNCTION SetForegroundWindow(nWinHandle) USING STDCALL FROM USER32.DLL
DLLFUNCTION GetWindow(nWinHandle,uCmd) USING STDCALL FROM USER32.DLL
DLLFUNCTION GetWindowTextA(nWinHandle,@cWindowName,nMax) USING STDCALL FROM USER32.DLL
DLLFUNCTION IsWindowVisible(nWinHandle) USING STDCALL FROM USER32.DLL
DLLFUNCTION GetWindowModuleFileNameA(nHandle,@cFileName,nSize) USING STDCALL FROM USER32.DLL
DLLFUNCTION IsIconic(nWinHandle) USING STDCALL FROM USER32.DLL
DLLFUNCTION GetLastActivePopup(nWinHandle) USING STDCALL FROM USER32.DLL
DLLFUNCTION GetWindowThreadProcessId(nForegroundHwnd,@nRetProcId) USING STDCALL FROM USER32.DLL
DLLFUNCTION GetForegroundWindow() USING STDCALL FROM USER32.DLL

*****************************************************************************************************************************
*** Läuft das Programm bereits?
*****************************************************************************************************************************
FUNCTION IsAppRunning(cExe,cTitle,lRestore)
/*
   Developed on Windows 98 2nd Edition using XBase++ 1.7

   Tested on Windows 98, 2000, and NT 4.0

   Richard Pulliam
   Richard@ClipperSolutions.com
*/
LOCAL nSearchColumn
LOCAL aRunningTasks
LOCAL i
LOCAL nWinHandleLast
LOCAL nWinHandleForeground
LOCAL nFindId
LOCAL nWinHandleFind
LOCAL nForeGroundId
LOCAL cColumnContents
LOCAL nPos
LOCAL nLenRunTasks

lRestore := IIf(lRestore == NIL, .T., lRestore) // default to restore running app
nSearchColumn := IIf(cExe#NIL, 2, 3) // what column to do search on, title or exe?
cExe := IIf(cExe == NIL, "", AllTrim(Upper(cExe)))
cTitle := IIf(cTitle == NIL, "", AllTrim(Upper(cTitle)))

aRunningTasks := GetRunningTasks() // returns a multidimensional array
                                 // of row form {nHandle,ExeName,Title}
nLenRunTasks := Len(aRunningTasks)
IF WinNT() .AND. !EMPTY(cExe)
   // this is because API function GetModuleBaseNameA does not return
   // a full path and equivalent commands like GetModuleFileName
   // did not work properly
   cExe := IIf((nPos := RAt("\", cExe)) > 0, SubStr(cExe, nPos + 1), cExe)
ENDIF

FOR i := 1 TO nLenRunTasks
   cColumnContents := AllTrim(Upper(aRunningTasks[i, nSearchColumn]))
   IF cExe+cTitle == cColumnContents // running
      IF .NOT. lRestore
         RETURN(.T.)
      ELSE
         nWinHandleFind := aRunningTasks[i, 1]
         nWinHandleForeground := GetForegroundWindow()
         nForeGroundId := GetWindowThreadProcessId(nWinHandleForeground, 0)
         nFindId := GetWindowThreadProcessId(nWinHandleFind, 0)
         IF .NOT. (nForeGroundId == nFindId) .OR. .NOT. (IsIconic(nWinHandleFind) == 0)
           nWinHandleLast := GetLastActivePopup(nWinHandleFind)
           IF .NOT. (IsIconic(nWinHandleLast) == 0)
             ShowWindow(nWinHandleLast, SW_RESTORE)
           ENDIF
           BringWindowToTop(nWinHandleLast)
           SetForegroundWindow(nWinHandleLast)
         ENDIF
         RETURN(.T.)
      ENDIF
   ENDIF
NEXT
RETURN(.F.)

*****************************************************************************************************************************
*** Die laufenden Programme zusammensuchen
*****************************************************************************************************************************
STATIC FUNCTION GetRunningTasks()

LOCAL aSize := {0, 0}
LOCAL aPos := {0, 0}
LOCAL oDlg
LOCAL aList

oDlg := XbpDialog():new(AppDesktop(), , aPos, aSize, , .F.)
oDlg:clipSiblings := .T.
oDlg:drawingArea:ClipChildren := .T.
oDlg:create()
aList := GetTaskList(oDlg:gethWnd( )) // Get a list of all running programs
oDlg:destroy()

RETURN(aList)

*****************************************************************************************************************************
*** Die Taskliste zusammenstellen
*****************************************************************************************************************************
#DEFINE GW_HWNDNEXT         2

STATIC FUNCTION GetTaskList( nWinHandle )
LOCAL aList:={}
LOCAL cWindowName
LOCAL nVisible
LOCAL nSize := 256
LOCAL nBytes
LOCAL cFileName
LOCAL aProcesses
LOCAL nPos
LOCAL nId

IF WinNT()
   aProcesses := GetNTProcesses()
ENDIF

WHILE(nWinHandle # 0)
   cWindowName := Space(nSize)
   nBytes := GetWindowTextA(nWinHandle, @cWindowName, nSize)
   IF nBytes # 0
      cWindowName := Left(cWindowName, nBytes)
      nVisible := IsWindowVisible(nWinHandle)
      IF nVisible == 1
         IF .NOT. WinNT() // Win 95 or 98
            cFileName := Space(nSize)
            nBytes := GetWindowModuleFileNameA(nWinHandle, @cFileName, nSize)
            AAdd(aList,{nWinHandle,Left(cFileName, nBytes - 1), cWindowName})
         ELSE // executing in NT family
            nId := 0
            GetWindowThreadProcessId(nWinHandle,@nId)
            IF (nPos := AScan(aProcesses, nId)) > 0
               cFileName := aProcesses[nPos, 2]
               AAdd(aList, {nWinHandle, cFileName, cWindowName})
            ENDIF
         ENDIF
      ENDIF
   ENDIF
   nWinHandle := GetWindow(nWinHandle, GW_HWNDNEXT)
ENDDO

RETURN(aList)

*****************************************************************************************************************************
***
*****************************************************************************************************************************
#DEFINE PROCESS_ALL_ACCESS 2035711 // hex 1F0FFF

DLLFUNCTION OpenProcess(nDesiredAccess, lInheritHandle, nProcessId) ;
   USING STDCALL FROM KERNEL32.DLL

DLLFUNCTION GetModuleBaseNameW(hProcess, hModule, @lpFileName, @nSize) ;
   USING STDCALL FROM PSAPI.DLL

DLLFUNCTION CloseHandle(nProcessHandle) USING STDCALL FROM KERNEL32.DLL

*****************************************************************************************************************************
***
*****************************************************************************************************************************
STATIC FUNCTION GetNTProcesses()

LOCAL aProcessIds
LOCAL i
LOCAL nProcessHandle
LOCAL aRetVal := {}
LOCAL naHandleForProcess
LOCAL cFileName
LOCAL nSize := 0
LOCAL nBytes
LOCAL j
LOCAL nLenIds
LOCAL nLenHandles

aProcessIds := EnumerateProcesses()
nLenIds := Len(aProcessIds)
FOR i := 1 TO nLenIds
   // get a handle to the process
   nProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, 0, aProcessIds[i])
   IF nProcessHandle > 0
      // get an array of the module handles for the specified process
      naHandleForProcess := EnumerateProcessModules(nProcessHandle)
      IF (nLenHandles := Len(naHandleForProcess))>0
         FOR j := 1 TO nLenHandles
            cFileName := SPACE(256)
            // GetModuleBaseName and GetModuleBaseNameA do not work here
            // GetModuleFileName .and GetModuleFileNameA do not work here
            nBytes := GetModuleBaseNameW(nProcessHandle, naHandleForProcess[j],;
                      @cFileName, @nSize)
            IF nBytes > 0
               cFileName := CleanUnicode(cFileName)
               AAdd(aRetVal, {aProcessIds[i], cFileName})
            ENDIF
         NEXT
      ENDIF
      CloseHandle(nProcessHandle)
   ENDIF
NEXT
RETURN(aRetVal)

*****************************************************************************************************************************
***
*****************************************************************************************************************************
STATIC FUNCTION CleanUnicode(cFileName)

cFileName := Upper(StrTran(cFileName, " ", ""))
cFileName := StrTran(cFileName, CHR(0), "")

RETURN(cFileName)

*****************************************************************************************************************************
***
*****************************************************************************************************************************
DLLFUNCTION EnumProcesses(@cProcesses,nSize,@nReturned) ;
   USING STDCALL FROM PSAPI.DLL

*****************************************************************************************************************************
*** Klasse für eine Fortschrittsanzeige
*****************************************************************************************************************************
STATIC FUNCTION EnumerateProcesses()

LOCAL cProcesses:=SPACE(1024)
LOCAL nSize := 1024
LOCAL nReturned := 0
LOCAL nRetVal := 0
LOCAL nElements
LOCAL i
LOCAL nVal
LOCAL naProcessIds := {}

nRetVal:=EnumProcesses(@cProcesses,nSize,@nReturned)

IF nRetVal # 0
   nElements := nReturned / 4
   FOR i := 1 TO nElements
      nVal := BIN2U(SubStr(cProcesses, 4 * (i - 1) + 1, 4))
      AAdd(naProcessIds, nVal)
   NEXT
ENDIF

RETURN(naProcessIds)

*****************************************************************************************************************************
***
*****************************************************************************************************************************
DLLFUNCTION EnumProcessModules(hProcess,@hMod,nSizeOf,@nBytesNeeded) ;
   USING STDCALL FROM PSAPI.DLL

*****************************************************************************************************************************
***
*****************************************************************************************************************************
STATIC FUNCTION EnumerateProcessModules(nProcessHandle)
LOCAL nSize := 4096
LOCAL nReturned := 0
LOCAL nRetVal := 0
LOCAL nVal
LOCAL cModuleHandles := SPACE(4096)
LOCAL naHandleForProcess := {}
LOCAL nElements
LOCAL i

nRetVal:=EnumProcessModules(nProcessHandle,@cModuleHandles,nSize,@nReturned)
IF nRetVal # 0
   nElements := nReturned / 4
   FOR i := 1 TO nElements
      nVal := BIN2U(SubStr(cModuleHandles, 4 * (i - 1) + 1, 4))
      AAdd(naHandleForProcess,nVal)
   NEXT
ENDIF

RETURN(naHandleForProcess)

*****************************************************************************************************************************
***
*****************************************************************************************************************************
#INCLUDE "OS.CH"

STATIC FUNCTION WinNT()

RETURN(OS(OS_FAMILY) == "WINNT")

*****************************************************************************************************************************
***
*****************************************************************************************************************************

Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: Programm bereits gestartet ?

Beitrag von AUGE_OHR »

hi,

ich habe auch so was früher benutzt, aber "soviel" Code muss nicht sein ...

Code: Alles auswählen

PROCEDURE AppSys
LOCAL cTitle  := "Xbase++ NeroCOM"
LOCAL hWndDlg := DllCall("User32.dll",DLL_STDCALL,"FindWindowA",0,cTitle)
   IF !(hWndDlg == 0)
      DllCall("User32.dll",DLL_STDCALL,"SetForegroundWindow",hWndDlg)
      DllCall("User32.dll",DLL_STDCALL,"BringWindowToTop",hWndDlg)
      DllCall("User32.dll",DLL_STDCALL,"ShowWindow",hWndDlg,1)
      DllCall("User32.dll",DLL_STDCALL,"UpdateWindow",hWndDlg)
      *** It is a second instance....  Bye Bye
      QUIT
   ENDIF
Return
das tut es auch.

Bemerkung : es wird nach dem Dialog:Title "gesucht"
gruss by OHR
Jimmy
Antworten