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

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Micoute
Messages : 2583
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

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

Message 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.
Dernière modification par Micoute le lun. 28/oct./2019 15:06, modifié 1 fois.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
Ar-S
Messages : 9539
Inscription : dim. 09/oct./2005 16:51
Contact :

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

Message 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
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Micoute
Messages : 2583
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

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

Message 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.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Marc56
Messages : 2196
Inscription : sam. 08/févr./2014 15:19

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

Message 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:
Avatar de l’utilisateur
Zorro
Messages : 2186
Inscription : mar. 31/mai/2016 9:06

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

Message 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



Dernière modification par Zorro le lun. 28/oct./2019 10:05, modifié 2 fois.
Marc56
Messages : 2196
Inscription : sam. 08/févr./2014 15:19

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

Message par Marc56 »

@Zorro: chapeau! :!: :P
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

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

Message 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
Avatar de l’utilisateur
Ar-S
Messages : 9539
Inscription : dim. 09/oct./2005 16:51
Contact :

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

Message par Ar-S »

Pas con cette idée Ollivier.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
Naheulf
Messages : 193
Inscription : dim. 10/mars/2013 22:22
Localisation : France

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

Message 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é...
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

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

Message 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
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Avatar de l’utilisateur
Zorro
Messages : 2186
Inscription : mar. 31/mai/2016 9:06

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

Message 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
Avatar de l’utilisateur
GallyHC
Messages : 1708
Inscription : lun. 17/déc./2007 12:44

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

Message 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
Configuration : Tower: Windows 10 (Processeur: i7 "x64") (Mémoire: 16Go) (GeForce GTX 760 - 2Go) - PureBasic 5.72 (x86 et x64)
Marc56
Messages : 2196
Inscription : sam. 08/févr./2014 15:19

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

Message 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 ?
Avatar de l’utilisateur
Ar-S
Messages : 9539
Inscription : dim. 09/oct./2005 16:51
Contact :

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

Message par Ar-S »

Excellent ce code de netmaestro.
Merci pour la trouvaille.
~~~~Règles du forum ~~~~
⋅.˳˳.⋅ॱ˙˙ॱ⋅.˳Ar-S ˳.⋅ॱ˙˙ॱ⋅.˳˳.⋅
W11x64 PB 6.x
Section HORS SUJET : ICI
LDV MULTIMEDIA : Dépannage informatique & mes Logiciels PB
UPLOAD D'IMAGES : Uploader des images de vos logiciels
Avatar de l’utilisateur
cage
Messages : 604
Inscription : ven. 16/oct./2015 18:22
Localisation : France
Contact :

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

Message 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
  
■ Win10 Pro 64-bit (Intel Celeron CPU N2920 @ 1.86GHz, 4,0GB RAM, Intel HD Graphics) & PB 6.12 LTS
■ Vivre et laisser vivre.
■ PureBasic pour le fun
■ Gérard sur le forum Anglais
■ Mes sites: http://pbcage.free.fr - http://yh.toolbox.free.fr
Répondre