Seite 1 von 1

.EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 12:29
von BIK
Ich würde gerne, dass das .exe vom Benutzer nur 1x pro Rechner gestartet werden kann.
Gibt es dazu einen Befehl für xBase++ 1.8 ?

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 12:46
von Jan
Nein. Aber Du kannst feststellen, ob das Programm schon mal gestartet wurde, und dann einen neuen Start verhindern. Das wurde hier im Forum auch schon mal diskutiert mit verschiedenen Lösungsansätzen, mußt Du mal kurz nach suchen.

Jan

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 13:00
von Martin Altmann

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 14:24
von BIK
herzlichen Dank!

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 14:25
von Rolf Ramacher
oder so die Appsys.prg

Code: Alles auswählen

#include "DLL.CH"
#define MUTEX_ALL_ACCESS  2031617
#Define CRLF Chr(13)+Chr(10)

Proc Appsys

LOCAL cMutex:=Upper(AppName())+Chr(0)
LOCAL nH:=DllCall("KERNEL32.DLL", DLL_STDCALL,;
                  "OpenMutexA", MUTEX_ALL_ACCESS, 0, cMutex)

Set Date to German
Set Deleted On
Set Collation to German
Set Console ON
Set Charset to Ansi


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)

Return

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 14:35
von Jan
Ähm, Rolf, Dir ist schon klar was Martin genau 2 Beiträge vor Deinem geschrieben hat?

Jan

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 14:37
von Rolf Ramacher
Hi Jan

doppelt geschrieben hätl besser. sorry- ich hatte direkt gepostet. Ist ja aber auch nicht schlimm

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 14:44
von Jan
... wenn Du man bloß auch woanders so schnell schalten würdest ... Ich habe dort gerade meine letzte Antwort zu diesem Thema geschrieben, mehr wirst Du in dem betreffenden Thread nicht mehr von mir lesen.

Jan

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 14:46
von Tom
Davon abgesehen ist es so, wie Rolf das wiedergegeben hat, falsch, denn hier wird der Mutex gleich wieder freigegeben. Das sollte erst beim Beenden des Programms geschehen, sonst sagt das Ding nie "Programm läuft schon". :wink:

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 14:51
von Rolf Ramacher
Ich weiß nicht mehr von wem ich diesen Hinweis erhalten habe, ich ahbe es so eingebaut und funkt. tadellos

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 17:15
von Herbert
Ich habe die Mutex-Geschichte in der Appsys - und funktioniert.

Re: .EXE nur 1x starten

Verfasst: Fr, 14. Feb 2014 17:31
von BIK
ich hab mutex auch in der appsys und es funktioniert herrlich! :blob8:

Re: .EXE nur 1x starten

Verfasst: Sa, 15. Feb 2014 0:42
von brandelh
Tom hat geschrieben:Davon abgesehen ist es so, wie Rolf das wiedergegeben hat, falsch, denn hier wird der Mutex gleich wieder freigegeben. Das sollte erst beim Beenden des Programms geschehen, sonst sagt das Ding nie "Programm läuft schon". :wink:
auf den ersten Blick ... aber wenn so viele behaupten dass es funktioniert ... da musste ich mal in der MSDN nachsehen was da passiert ;-)

So wie ich das verstehe, kann man den Mutex mehrfach öffnen und feststellen ob man exclusiven Zugriff bekommt oder nicht.
Diesen exclusiven Zugriff gibt man mit ReleaseMutex wieder frei, der MUTEX handle bleibt aber bestehen bis CloseHandle aufgerufen wird.
Sobald das letzte Programm seinen handle freigibt (z.B. durch Programmende) wird der Mutex in Windows bereinigt.

LOCAL nH:=DllCall("KERNEL32.DLL", DLL_STDCALL, "OpenMutexA", MUTEX_ALL_ACCESS, 0, cMutex)

öffnet den Mutex, falls er schon angelegt wurde und dann ist nH > 0 ... das ist aber genau in diesem Programm nicht erwünscht und die Fehlermeldung folgt.
Nur wenn nH=0 ist, also nicht geöffnet werden konnte - weil er ja nicht existiert - nur dann wird er angelegt und das Programm weiter geführt.

Re: .EXE nur 1x starten

Verfasst: Sa, 15. Feb 2014 10:42
von Rudolf
Hallo,
ich mache es anders, mit der Methode sehe ich auch welche User aktiv sind, da ich auch für jeden User ein File beim Start nach dem Login schreibe. Beim Beenden wird das File autom. freigegegen.
Grüße
Rudolf

Code: Alles auswählen

FUNCTION makeappfile(nMod)
******************************************************************
local cFile := exename() + ".XUF"
static nUsrHnd
DEFAULT nUsrHnd to -1
DEFAULT nMod to 0
if nMod = 1 // close file
     if nUsrHnd > 0
          FCLOSE(nUsrHnd)
     endif
     return .t.
endif
if nUsrHnd = -1 // first Login

else
     if nUsrHnd > 0
          FCLOSE(nUsrHnd)
     endif
endif
IF (nUsrHnd := FCREATE( cFile )) == -1              // Exist
     dc_msgbox("The system " + exename() + " already started !!!, start cancelled", , , , ,3)
     return .f.
endif
FWRITE(nUsrHnd, cFile )
FCLOSE(nUsrHnd)
return .t.


FUNCTION checkrunning(cExe)
******************************************************************
local nUsrHnd
local cFile := cExe + ".exe.XUF"
IF (nUsrHnd := FCREATE( cFile )) == -1              // Exist
     return .t.
endif
FCLOSE(nUsrHnd)
filedelete(cFile)
return .f.

Re: .EXE nur 1x starten

Verfasst: Sa, 15. Feb 2014 11:07
von BIK
und wenn dir das Programm abstürzt, dann ist der User bis zum wirklichen Beenden als aktiv gespeichert!

Re: .EXE nur 1x starten

Verfasst: Sa, 15. Feb 2014 11:18
von Rudolf
Hallo,
aber nur wenn die Fehlermeldung ewig stehenbleibt. Ich habe einen Timeout drin
Grüße
Rudolf

Re: .EXE nur 1x starten

Verfasst: Mo, 17. Feb 2014 7:37
von Magic
Hi,

meine Lösung:

Code: Alles auswählen

   // Prüfe ob Programm bereits läuft
   IF CheckIfAppIsOpen( AppName(), .F. )[2]
      // Programm abbrechen, da es bereits läuft
      // !!! evtl. laufende Applikation nach vorne holen !!!
      QUIT
   ENDIF

Code: Alles auswählen

...
********************************************************************************
* Defines
********************************************************************************
#DEFINE PROCESS_QUERY_INFORMATION  1024
#DEFINE PROCESS_VM_READ              16


********************************************************************************
FUNCTION CheckIfAppIsOpen( cAppName, lClose )
 * Prüfe ob die Applikation <cAppName> bereits läuft
 * Parameter: cAppName: Name der Exe
 * Return: .T. für läuft, sonst .F.
********************************************************************************

   LOCAL lOpen      := .F., ;
         aProcesses := space(10240), ;
         cbNeeded   := 0,;
         nPid, ;
         nProcHandle, ;
         aModules   := space(4*10), ;
         cbNeeded2  := 0, ;
         n, ;
         nMax, ;
         cname      := space(64), ;
         nPidDel    := NIL, ;
         nAnzApp    := 0
//         xRet

   EnumProcesses( @aProcesses, LEN(aProcesses) , @cbNeeded )

   // Anzahl laufender Prozesse
   nMax := len(trim(aProcesses))/4

   FOR n:= 1 TO nMax
      nPid := Bin2U(substr(aProcesses,1+((n-1)*4),4))
      IF nPidDel==NIL .OR. (nPIdDel==nPid)
         nProcHandle  := OpenProcess( PROCESS_QUERY_INFORMATION + PROCESS_VM_READ ,0, nPid )
         IF EnumProcessModules( nProcHandle, @aModules,len(aModules)/4, @cbNeeded2) != 0
            cName := space(128)
//            xRet  := GetModuleBaseNameA( nProcHandle,bin2u(substr(aModules,1,4)),@cName,len(cName))
            GetModuleBaseNameA( nProcHandle,bin2u(substr(aModules,1,4)),@cName,len(cName))
            cName := strtran(cname,chr(0),"")
//            CloseHandle(nProcHandle)
            IF upper(Alltrim(cName))==upper(cAppName)
               nAnzApp += 1
               nProcHandle := OpenProcess(1,0,nPId)
               IF lClose
                  TerminateProcess(nProcHandle,1)
                  CloseHandle(nProcHandle)
               ENDIF
            ENDIF
         ENDIF
      ENDIF
   NEXT n

   IF nAnzApp > 1
      lOpen := .T.
   ENDIF

RETURN { nAnzApp, lOpen }



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 CloseHandle(nHandle);
            USING STDCALL FROM KERNEL32.DLL
DLLFUNCTION TerminateProcess(hProcess,uExitCode) ;
            USING STDCALL FROM KERNEL32.DLL

DLLFUNCTION BringWindowToTop( nHwnd ) ;
            USING STDCALL FROM USER32.DLL
DLLFUNCTION SetForegroundWindow( nHwnd ) ;
            USING STDCALL FROM USER32.DLL

Re: .EXE nur 1x starten

Verfasst: Di, 18. Feb 2014 3:33
von AUGE_OHR
Magic hat geschrieben:meine Lösung:
so was benutze ich auch.

zu beachten, bei Windows 8.1, die evtl. "Gruppierung" bei minimierten MDI Fenstern.
http://www.xbaseforum.de/viewtopic.php?f=23&t=7735