Page 1 sur 2

Comment puis-je savoir si un prog n'est pas déjà lancé?

Publié : lun. 19/févr./2007 13:11
par RV
Au lancement d'un de mes prog, je voudrais savoir s'il n'est pas déjà lancé.

En gros, peut-on vérifier q'il n'est pas présent dans le gestionnaire des tâches?

Merci pour vos réponses!

Re: Comment puis-je savoir si un prog n'est pas déjà lancé?

Publié : lun. 19/févr./2007 13:53
par Backup
RV a écrit :Au lancement d'un de mes prog, je voudrais savoir s'il n'est pas déjà lancé.

En gros, peut-on vérifier q'il n'est pas présent dans le gestionnaire des tâches?

Merci pour vos réponses!
de la part de Nico :D


 
  #MUTEX_ALL_ACCESS = $1F0001

Application.s= "Mon application"

Hmutex = OpenMutex_ ( #MUTEX_ALL_ACCESS , #False ,Application)
If Hmutex=0
     ;Si le mutex existe alors l'application est déjà lancée.
     ;sinon on le crée
    Hmutex = CreateMutex_ ( #Null , #True , Application)
     If Hmutex=0
         ;Fin du programme mutex non créer
         End
     EndIf
Else
     ;On recherche l'application
     ;pour la mettre au premier plan.
    Handle= FindWindow_ ( #Null , Application)
     ShowWindow_ (Handle, #SW_HIDE )
     ShowWindow_ (Handle, #SW_MINIMIZE )
     ShowWindow_ (Handle, #SW_RESTORE )
     End
EndIf

;Le reste du code ici
If OpenWindow (0, 431, 186, 325, 214, #PB_Window_SystemMenu , Application)
     Repeat
        Event= WaitWindowEvent ()
     Until Event = #PB_EventCloseWindow
EndIf

CloseHandle_ (Hmutex)
End

Publié : lun. 19/févr./2007 14:19
par Jacobus
une autre façon de faire qui me paraît plus simple à gérer
(c'est un code de Julien il me semble) je l'ai commenté car il faut garder à l'esprit que c'est le nom de la fenêtre qui est recherché et pas le nom de l'exécutable. Créer un exe à partir de l'exemple pour tester.

Code : Tout sélectionner

;Vérification programme en cours
#Application = "Mon programme" ; Il faut le nom de la fenêtre et NON celui de l'exécutable!
Procedure ExeLance(nomfenetre$) 
 F=FindWindow_(0, nomfenetre$) 
  If F<>0 
   ProcedureReturn 1 ; retourne 1 si détecté 
  Else 
   ProcedureReturn 0 ; retourne 0 si non détecté 
  EndIf 
EndProcedure

Enumeration
#WIN:#BtnClose
EndEnumeration

res=ExeLance(#Application);on passe le nom de la fenêtre en param
;en fonction de l'état de la fenêtre, celle-ci est restaurée au premier plan
;ou le programme est démarré s'il ne l'était pas 
  If res=1 
     Handle=FindWindow_(#Null, #Application) 
      ShowWindow_(Handle,#SW_HIDE)  
      ShowWindow_(Handle,#SW_MINIMIZE) 
      ShowWindow_(Handle,#SW_RESTORE)
    End 
  EndIf 
  
 If OpenWindow(#WIN,0,0,300,200, #Application, #PB_Window_SystemMenu| #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget|#PB_Window_ScreenCentered|#PB_Window_TitleBar)<>0 And CreateGadgetList(WindowID(#WIN))<>0 
  
  ButtonGadget(#BtnClose,20,20,260,160,"FERMER")
  
 Repeat
  Event = WaitWindowEvent() 
    If Event = #PB_Event_Gadget
       Select EventGadget() 
              Case #BtnClose:Event = #PB_Event_CloseWindow         
       EndSelect  
    EndIf 
  Until Event = #PB_Event_CloseWindow
  
EndIf
End 

Publié : lun. 19/févr./2007 16:24
par brossden
Le programme de Dobro me parait trés fiable, alors que celui de Jacobus sousentend que l'on connais en permance le Libellé qui est dans la fenetre, mais comment resoudre le problème des programmes qui font évoluer ce même libéllé (par exemple avec un pourcentage d'une fonction longue à effectuée, style un téléchargement....

Deplus je ne vois vraiment pas la simplicité apportée !

Publié : lun. 19/févr./2007 17:43
par Jacobus
C'est pourtant pas compliqué...
J'ai mis l'exemple avec une constante, mais initialement c'est une variable chaîne qui est passée en paramètre. Donc tu peux la faire varier, non? Pour ce qui est de la simplicité, ne pas utiliser de mutex me paraît entrer dans cet optique, mais c'est mon point de vue.

Quant à la fiabilité du code proposé par Dobro, je ne la remet pas en cause, je m'en suis déjà servi. A contrario, tu déclares, en clair, que j'aurai mieux fais de m'abstenir plutôt que de proposer ce code.
Donc si ça ne te plaît pas c'est pareil :)

Publié : lun. 19/févr./2007 18:04
par Sami
Voila d'un source code bien utile. Justement je cherchais une solution à ce problème pour un programme perso.

Le code donné par Jacobus est portable par rapport à celui de Dobro. Ce qui m'interesse plus dans mon cas, car mon programme doit tourner sous Windows, Linux et MacOs.

En tout ca merci à vous deux! Vous avez fait un heureux.

Publié : lun. 19/févr./2007 18:15
par Jacobus
Le code donné par Jacobus est portable par rapport à celui de Dobro
Désolé mais je ne crois pas, les deux codes utilisent des API Windows.

Publié : lun. 19/févr./2007 18:26
par nico
Il est peut être possible d'en faire un tout en Pb vu qu'il intègre maintenant les fonctions Mutex mais il manquerait apparemment IsMutex, a essayé en tout cas.

Publié : mar. 20/févr./2007 13:11
par Kwai chang caine
Bonjour à tous

Pour tester le nombre d'instances d'un programme présent dans le gestionnaire des taches, j'avais trouvé ce code. 8)

Il marche super bien et teste bien le nom du giciel comme il apparait dans le gestionnaire des taches, car avec les fenetres c'est moins sûr comme le dit BROSSDEN.

Honte à moi je ne me rapelle plus de qui il est. :oops:

Il etait plus complet, mais j'ai gardé la partie NT.

Code : Tout sélectionner

Procedure NombreInstancesProgramme(Programme.s) ; Version pour NT seulement
   
 Structure PROCESS_MEMORY_COUNTERS 
  cb.l 
  PageFaultCount.l 
  PeakWorkingSetSize.l 
  WorkingSetSize.l 
  QuotaPeakPagedPoolUsage.l 
  QuotaPagedPoolUsage.l 
  QuotaPeakNonPagedPoolUsage.l 
  QuotaNonPagedPoolUsage.l 
  PageFileUsage.l 
  PeakPagefileUsage.l 
 EndStructure 

 #OWNER_SECURITY_INFORMATION = $00000001 
 #GROUP_SECURITY_INFORMATION = $00000002 
 #DACL_SECURITY_INFORMATION  = $00000004 
 #SACL_SECURITY_INFORMATION  = $00000008 
 #PROCESS_TERMINATE          = $0001 
 #PROCESS_CREATE_THREAD      = $0002  
 #PROCESS_SET_SESSIONID      = $0004  
 #PROCESS_VM_OPERATION       = $0008  
 #PROCESS_VM_READ            = $0010  
 #PROCESS_VM_WRITE           = $0020  
 #PROCESS_DUP_HANDLE         = $0040  
 #PROCESS_CREATE_PROCESS     = $0080  
 #PROCESS_SET_QUOTA          = $0100  
 #PROCESS_SET_INFORMATION    = $0200  
 #PROCESS_QUERY_INFORMATION  = $0400  
 #PROCESS_ALL_ACCESS         = #STANDARD_RIGHTS_REQUIRED | #SYNCHRONIZE | $FFF 
 #NbProcessesMax = 10000 
 Global Dim ProcessesArray(#NbProcessesMax) 
 Global Dim ListeProceduresEnCours.s(500) 
   
 If OpenLibrary(0, "psapi.dll") 
  
  EnumProcesses      = GetFunction(0, "EnumProcesses") 
  EnumProcessModules = GetFunction(0, "EnumProcessModules") 
  GetModuleBaseName  = GetFunction(0, "GetModuleBaseNameA") 

  If EnumProcesses And EnumProcessModules And GetModuleBaseName  ; Be sure we have detected all the functions 
      
   CallFunctionFast(EnumProcesses, ProcessesArray(), #NbProcessesMax, @nProcesses) 
   x = 0
      
   For k = 1 To nProcesses / 4 
 
    hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, 0, ProcessesArray(k-1)) 
        
    If hProcess 
 
     CallFunctionFast(EnumProcessModules, hProcess, @BaseModule, 4, @cbNeeded) 
     Name$ = Space(255) 
     CallFunctionFast(GetModuleBaseName, hProcess, BaseModule, @Name$, Len(Name$)) 
 
     If FindString(Name$, Programme, 1) <> 0 
      NbreInstance + 1
      CloseHandle_(hProcess) 
     EndIf
      
     CloseHandle_(hProcess) 
 
    EndIf 
 
   Next 
      
  EndIf 
  
  CloseLibrary(0) 
 
 EndIf 
 
 ProcedureReturn NbreInstance
  
EndProcedure 
Si ça peut servir à quelqu'un ???

Publié : mar. 20/févr./2007 17:44
par nico
Je ne vois pas ce qui vous gêne avec les mutex, il y a juste trois fonctions, ouvrir, créer et fermer, c'est assez simple, non?

Publié : mar. 20/févr./2007 19:28
par RV
Je pars sur celui de Dobro mais garde les autres sous le coude.

Merci a vous car je n'avais pas de solution et je me retrouve avec 3.

A+

Publié : mar. 18/août/2009 0:09
par gansta93
Bonjour,

Je fais remonter ce topic parce qu'une question intéressente a été pausée : est-ce possible de faire le même code que Nico mais en version portable en utilisant les mutex via les fonctions PB natives ?

Je ne voi pas comment, mais si quelqu'un a trouvé, je lui en serait reconnaissant pendant un sacré bout de temps ^^. :D

Publié : mar. 18/août/2009 0:51
par Ollivier
Kwai chang caine a écrit :Honte à moi je ne me rapelle plus de qui il est. Embarassed
De Chris.

Publié : mar. 18/août/2009 14:40
par lepiaf31
J'ai à peu près le même code mais au lieu de vérifier simplement le nom du processus, je vérifie le chemin complet du processus (on ne sait jamais si le nom du processus est le meme que celui d'un autre programme ^^ ):

Code : Tout sélectionner

Procedure ProgramAlreadyLaunch()
  Result = 0
  
  library = OpenLibrary(#PB_Any, "psapi.dll")
  If library
    ;on cherche le chemin complet du processus en cours
    hCurrentProcess = GetCurrentProcess_()
    ProcessPathSize = 1000
    ProcessPath.s = Space(ProcessPathSize)
    CallFunction(library, "GetModuleFileNameExA", hCurrentProcess, 0, @ProcessPath, ProcessPathSize)
    CurrentProcessPath.s = Trim(ProcessPath)
    CloseHandle_(hCurrentProcess)
  
    
    ArraySize = 1000
    NbProcesses.l
    Dim Processes(ArraySize)
    CallFunction(library, "EnumProcesses", @Processes(), ArraySize, @NbProcesses)
    NbProcesses = NbProcesses / 4
    
    Found = 0
    For i=1 To NbProcesses
      hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION|#PROCESS_VM_READ, #False, Processes(i-1))
      If hProcess
        ProcessPathSize = 2000
        ProcessPath.s = Space(ProcessPathSize)
        CallFunction(library, "GetModuleFileNameExA", hProcess, 0, @ProcessPath, ProcessPathSize) ;chemin du processus
        CloseHandle_(hProcess)
        
        ;on a trouvé un processus avec le meme chemin de lancement
        ;/!\ il faut trouver le processus 2 fois: une fois pour le programme en cours et une pour le programme deja lancé
        
        If Trim(ProcessPath) = CurrentProcessPath
          Found+1
          If Found = 2
            Result = 1
            Break
          EndIf
        EndIf
      EndIf
    Next
    
    CloseLibrary(library)
  EndIf
  ProcedureReturn Result
EndProcedure

If ProgramAlreadyLaunch()
  MessageRequester("Erreur", "Programme déjà lancé")
  End
EndIf

OpenConsole()
Input()
Compilez un executable et lancez-le 2 fois, vouz verrez ca marche très bien ;)

Publié : mar. 18/août/2009 16:54
par gansta93
Bien bien, ça en fait du code ^^... mais faut croire que Linux n'est pas très coopératif ou que les fonctions pb sont trop "limitées"... :winkk: