Page 1 sur 3

[Résolu] Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 9:42
par Micoute
Bonjour à tous,

ce n'est pas que ce soit embêtant, mais j'aimerais que me programmes compilés ne puissent pas être relancés s'ils sont déjà en exécution.

Il y a certainement une méthode, mais je ne la connais pas, alors si vous la connaissez, voulez-vous s'il vous plaît m'en faire profiter ?

Je vous en remercie d'avance.

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 10:45
par Ar-S
J'utilisais ça il y a un moment.
A voir s'il marche encore.

Code : Tout sélectionner

;Autor: ts-soft

EnableExplicit

Procedure CheckRunningPureBasic(Name.s)
  Protected result.l, Snapshot.l, ProcessFound.l, PN$, Process.PROCESSENTRY32
  Process\dwSize = SizeOf(PROCESSENTRY32)
  Snapshot = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0)
  If Snapshot
    ProcessFound = Process32First_(Snapshot, Process)
    While ProcessFound
      PN$ = UCase(PeekS(@Process\szExeFile, #PB_Any, #PB_Ascii))
      If UCase(Name) = GetFilePart(PN$) : result = #True : Break : EndIf
      ProcessFound = Process32Next_(Snapshot, Process)
    Wend
    CloseHandle_(Snapshot)
  EndIf
  ProcedureReturn result
EndProcedure

If CheckRunningPureBasic("PureBasic.exe")
  MessageRequester("","Programme est en cours d'exécution.",0)
Else
  MessageRequester("","Rien lancé.",0)
EndIf

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 12:55
par Micoute
Merci beaucoup Ar-s, mais hélas apparemment il ne fonctionne pas chez moi, peut-être que c'est dû au fait que j'utilise la version x64.

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 13:50
par Marc56
Sans API

Code : Tout sélectionner

; Vérification de la présence d'un programme en mémoire 
; Marc56 - 24/10/19 - PureBasic toutes versions - Windows >= 2000
; Utilisation de la commande Windows tasklist.exe

; Ligne de commande qui est envoyée:
; tasklist /FI "IMAGENAME eq PureBasic.exe"
; tasklist /? pour voir les autres possibilités

EnableExplicit

Define MyProgram$ = "PureBasic.exe"

Define Parameter$ = "/FI "+ Chr(34) + "IMAGENAME eq " + MyProgram$ + Chr(34) + " /NH"
Debug Parameter$

Define Run = RunProgram("tasklist", Parameter$, "", #PB_Program_Open | #PB_Program_Read)

If Run 
    Define Line$, Running$
    Debug "-----------------------------------"
    While ProgramRunning(Run) 
        If AvailableProgramOutput(Run)
            Define Line$ = ReadProgramString(Run)
            Debug Line$
            Running$ + Line$
        EndIf   
    Wend
    Debug "-----------------------------------"
    CloseProgram(Run)
Else  
    Running$ = "Rien"
EndIf

If StringField(Running$, 1, " ") = MyProgram$
    MessageRequester("Désolé.", 
                     MyProgram$ + " est déjà en fonctionnement.", 
                     #PB_MessageRequester_Warning)
Else
    MessageRequester("Information", 
                     "OK, la place est libre", 
                     #PB_MessageRequester_Info)  
EndIf

End
Mais ceci marche pour un autre programme que celui en cours.
Pour que le programme se teste lui-même il faut compter la présence de plus d'une fois le même nom.

:wink:

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 14:07
par Zorro
comme ça , ça fonctionne bien ;)

Code : Tout sélectionner


; Code de Nico  :o)
; verifie si le prg en cours est deja lancé
; Lancez ce code 2 fois
; vous verrez que la deuxieme fois il est fermé

Declare deja_lance(Application.s)
Application.s= "Mon application" ; nom de l'application a empecher de se lancer 2 fois



;Le Programme de test :
deja_lance(Application.s) ; on test si le prg est deja lancé
If OpenWindow (0, 431, 186, 325, 214, Application,#PB_Window_SystemMenu) ; ici on a bien mis le meme NOM c'est important !!
		Repeat
				Event= WaitWindowEvent ()
		Until Event = #PB_Event_CloseWindow
EndIf

CloseHandle_(Hmutex)
End




; **************** Procedure Zone ***************************
Procedure deja_lance(Application.s)
		#MUTEX_ALL_ACCESS = $1F0001
		Hmutex = OpenMutex_( #MUTEX_ALL_ACCESS , #False ,Application)		
		If Hmutex=0			
				Hmutex = CreateMutex_( #Null , #True , Application)
				If Hmutex=0					
						End
				EndIf
		Else			
				Handle= FindWindow_( #Null , Application)
				ShowWindow_(Handle, #SW_HIDE )
				ShowWindow_(Handle, #SW_MINIMIZE )
				ShowWindow_(Handle, #SW_RESTORE )
				End
		EndIf
EndProcedure




Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 15:43
par Marc56
@Zorro: chapeau! :!: :P

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 19:54
par Ollivier
Une méthode sans API et multi-plateforme.

1) Vérifie si "AlreadyExecuted.TXT" existe.
2) Si oui, terminer le programme
3) Si non, créée un fichier vide "AlreadyExecuted.TXT"
4) Exécution normale du programme.
5) Destruction du fichier "AlreadyExecuted.TXT"
6) Fin de programme

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 20:40
par Ar-S
Pas con cette idée Ollivier.

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : jeu. 24/oct./2019 22:30
par Naheulf
L'idée d'Olivier est une fausse bonne idée.

En occurrence cela pose problème si le programme est interrompu de manière brutale:
1) Vérifie si "AlreadyExecuted.TXT" existe.
2) Si oui, terminer le programme
3) Si non, créée un fichier vide "AlreadyExecuted.TXT"
4) Exécution normale du programme.
5) Fermeture anticipée du programme (crash, perte d'alimentation de l'ordinateur, mise à jour windows, ...)

1) Vérifie si "AlreadyExecuted.TXT" existe.
2) Si oui, terminer le programme

1) Vérifie si "AlreadyExecuted.TXT" existe.
2) Si oui, terminer le programme

Sans compter qu'en l'état ça ne fonctionne pas si le programme est lancé rapidement plusieurs d'fois d'affilé...

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : ven. 25/oct./2019 7:18
par GallyHC
Bonjour,

Pour l'idée d'Ollivier, oui comme le dit "Naheulf" c'est une fausse bonne idée vu comme cela. Mais si on "lock" le fichier (on l'ouvre mais on ne le ferme pas), celui-ci ne peut être écrit par un autre instance d'un programme. Donc on test si on peut écrire dans ce fichier et si oui c'est que le programme et non actif normalement (PB et bien fait a ce sujet de mémoire, il ferme les fichiers même en cas de plantage et au pire on gère le plantage avec un "OnErrorCall").

Cordialement,
GallyHC

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : ven. 25/oct./2019 9:45
par Zorro
ben le plus simple reste la methode du mutex ... :mrgreen:

Reedit
j'ajoute que le code que j'ai posté est un code de Nico ...

j'ai mis un moment a retrouver l'auteur ... sorry
ce code n'etait pas Taggé ....ce qui est étonnant dans mes archives...
mais ça me chatouillais de ne pas savoir qui etait l'auteur a qui j'ai piqué ce code ..
j'aurai du le savoir, car a Nico, je lui ai piqué pleins de trucs :lol:

topic original :
https://www.purebasic.fr/french/viewtop ... emier+plan.

voila, rendons a César

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : ven. 25/oct./2019 10:30
par GallyHC
@Zorro > le plus simple pour windows oui, d’ailleurs c'est la solution que j'utilise moi aussi.

Par contre pour du multiOS c'est peut-être une solution viable et je ne répondais que sur le fait de rendre la solution plus viable ^^.

Cordialement,
GallyHC

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : ven. 25/oct./2019 10:35
par Marc56
Une version avec utilisation des Semaphores et API (par netmaestro)
http://forums.purebasic.com/english/vie ... 061#p95061

Code : Tout sélectionner

; Basé sur un code de netmaestro
; http://forums.purebasic.com/english/viewtopic.php?p=95061#p95061

*a = CreateSemaphore_(null,0,1,"PreviewModeSemaphore")
If *a <> 0 And GetLastError_()= #ERROR_ALREADY_EXISTS
    MessageRequester("Erreur", "Le programme est déjà lancé")
;     CloseHandle_(*a)
;     End
Else
    MessageRequester("", "Running...")
EndIf
Peut-on faire la même chose avec les fonctions Semaphore (ou Mutex) de PB ?

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : ven. 25/oct./2019 13:19
par Ar-S
Excellent ce code de netmaestro.
Merci pour la trouvaille.

Re: Empêcher un exécutable de se lancer plus d'une fois

Publié : ven. 25/oct./2019 13:52
par cage
Bonjour a tous,
Une façon de faire en utilisant les Mutex
Si l'application est déjà lancée, il est possible de
- ne rien faire
- lancer une nouvelle instance
- réactiver la première instance

Dans l'exemple si dessous, je réactive la première instance de l'application si lancée.
cage

Code : Tout sélectionner

EnableExplicit

OnErrorGoto(?ErrorHandler)

Global Mutex

#appname = "Mon application"
#runonce = #True    ; une seule instance autorisée.

;;; https://msdn.microsoft.com/en-us/library/windows/desktop/cc144179%28v=vs.85%29.aspx
Global TB_Message = RegisterWindowMessage_("TaskbarCreated")


CompilerIf #PB_Compiler_Debugger      ; choisir une valeur pour Mutex
  ;; On est dans l'IDE
  ;; Valeur utilisée uniquement dans l'IDE
  ;; Utilisez une valeur inférieure a 1000 (mille).
  #winMain = 999
CompilerElse
  ;; L'application est compilée.
  ;; Valeur utilisée par Mutex si besoin.
  ;; Utiliser une valeur unique par application.
  ;; Valeur du Mutex = "WindowClass_1111"
  #winMain = 1111
CompilerEndIf

CompilerIf #PB_Compiler_Debugger
  ;; On est dans l'IDE
CompilerElse
  ;; L'application est compilée.
  If TB_Message
    Mutex = CreateMutex_(#Null, #False, #appname)
    If GetLastError_() = #ERROR_ALREADY_EXISTS And #runonce ; une seule instance autorisée
      ;;;
      ;;; Same Mutex in memory, that same app is running ???
      ;;; 
      Define hWnd = FindWindow_("WindowClass_"+Str(#winMain), #NUL)
      If hWnd
        ;;;
        ;;; Same Mutex in memory and same ClassName, no doubt, is the same app.
        ;;;
        SendMessage_(hWnd,#WM_SYSCOMMAND, #SC_RESTORE,0)
        SetForegroundWindow_(hWnd)
        End
      Else
        ;;;
      EndIf
    EndIf
  Else
    ;; Desktop is not activated, then no TaskBar (TB)
    End
  EndIf
CompilerEndIf

; Form
ExamineDesktops()
#appWidth  = 550
#appHeight = 170
Define X = (DesktopWidth(0)-#appWidth)/2
Define Y = (DesktopHeight(0)-#appHeight)/2

Define Flags = #PB_Window_TitleBar|#PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget

If OpenWindow(#winMain, X, Y, #appWidth, #appHeight, #appname, Flags)
  Define Event, indexMenu, indexGadget, indexGadgetType
  Repeat
    Event = WaitWindowEvent(20)
    Select Event
      Case #PB_Event_CloseWindow
        Break
    EndSelect
  ForEver
EndIf

ErrorHandler:
  
Define lHwd = FindWindow_("Progman", #NUL)
ShowWindow_(lHwd, 8)
ReleaseMutex_(Mutex)
End