Page 1 sur 2

Fermeture programme déjà lancé [RESOLU]

Publié : lun. 22/mars/2010 14:31
par DarkIchigo
Salut a tous,

ayant commencé depuis peu la programmation sous PB (1 semaine env) et ne connaissant encore que peu de choses a l'heure actuelle, je sollicite votre aide pour un programme tout simple :

J'essaye de créer un programme qui a 2 boutons, l'un qui ferme un logiciel (Rainmeter) et l'autre qui l'ouvre. (dans cet ordre).
En effet, Rainmeter est chargé au lancement de Windows et je voudrais donc pouvoir le fermer avant de lancer par exemple une session de jeu, puis le relancer après.

Voici ma proposition de code :

Code : Tout sélectionner

;- Enumeration
Enumeration
  #Window_0
  #Button_0 
  #Button_1
  #Button_2
  #Text_0 
  #Text_1 
EndEnumeration
#Window_0_largeur=300
#Window_0_hauteur=150

;- Procedures
Procedure load_rainmeter_evenement()
  RunProgram("C:\Program Files\Rainmeter\Rainmeter.exe")
EndProcedure

Procedure kill_rainmeter_evenement()
;???
EndProcedure

;- Fenetre
  OpenWindow(#Window_0, 200, 200, #Window_0_largeur, #Window_0_hauteur, "Load / Kill for Rainmeter", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_TitleBar)
    TextGadget(  #Text_0,   75, 15, 150, 35, "Wana play ?",    #PB_Text_Center)
    ButtonGadget(#Button_0, 75, 30, 150, 35, "Kill it !")
    TextGadget(  #Text_1,   75, 75, 150, 35, "Done playing ?", #PB_Text_Center)
    ButtonGadget(#Button_1, 75, 90, 150, 35, "Load it !")

;- WaitWindowEvent()
  Repeat
    EventID = WaitWindowEvent()

    If EventID = #PB_Event_Gadget

      Select EventGadget()

        Case #Button_0
          kill_rainmeter_evenement()

        Case #Button_1
          load_rainmeter_evenement()

      EndSelect

    EndIf

  Until EventID = #PB_Event_CloseWindow

End  
Mon pb viens de la procédure "Procedure kill_rainmeter_evenement()"
je ne sais pas quoi mettre ici pour fermer Rainmeter si il étais déjà lancé avant mon programme.

Ni d'ailleur comment faire pour le fermer si je le lance a partir de mon programme.

Merci d'avance de votre aide

Re: Fermeture programme déjà lancé

Publié : lun. 22/mars/2010 15:56
par Ar-S
Bonjour et bienvenue.

Je te conseils de tester la DroopyLib http://sourceforge.net/projects/droopyslib/files/
Elle contient de très nombreuses fonctions dont celle gérant la découverte des Handle des fenêtres ainsi que le KillProcess
C'est exactement ce dont tu as besoin.

Un seul bouton suffirait.

En gros si tu clique ET que le prog est ouvert, il le ferme, sinon il le lance (via ton RunProgram)

Je vais essayer de te faire un p'tit code.

Re: Fermeture programme déjà lancé

Publié : lun. 22/mars/2010 16:20
par Ar-S
Voilou

Note bien que j'ai utilisé les procédure de la Droopy Lib que j'ai donc ajouté au code.
Si tu installes cette lib, tu pourras virer toute cette 1ere partie (jusqu'à ----- Le programme-----).

Code : Tout sélectionner

;---- PROCEDURE KILLPROCESS récupéré de la DroopyLib-------
;---- Tu devras commenter ces lignes si tu l'installes -----
; Author: Hi-Toro tweaked by Droopy
; Date: 30. November 2003
; Return 1 if success / 0 if fail ( or proccess name don't exist )

#PROCESS_TERMINATE = $1 
#PROCESS_CREATE_THREAD = $2 
#PROCESS_VM_OPERATION = $8 
#PROCESS_VM_READ = $10 
#PROCESS_VM_WRITE = $20 
#PROCESS_DUP_HANDLE = $40 
#PROCESS_CREATE_PROCESS = $80 
#PROCESS_SET_QUOTA = $100 
#PROCESS_SET_INFORMATION = $200 
#PROCESS_QUERY_INFORMATION = $400 
#PROCESS_ALL_ACCESS = #STANDARD_RIGHTS_REQUIRED | #SYNCHRONIZE | $FFF 

ProcedureDLL KillProcess(PID) 
  phandle = OpenProcess_ (#PROCESS_TERMINATE, #False, PID) 
  If phandle <> #Null 
    If TerminateProcess_ (phandle, 1) 
      Result = #True 
    EndIf 
    CloseHandle_ (phandle) 
  EndIf 
  ProcedureReturn Result 
EndProcedure 


ProcedureDLL.s HandleToFileName(hwnd.i) 
  PID.i=0 
  GetWindowThreadProcessId_( hwnd, @PID ) 
  hProcess.i = OpenProcess_( #PROCESS_ALL_ACCESS, 0, PID ); 
  Name.s=Space(256) 
  
  psapi = OpenLibrary(#PB_Any,"PSAPI.DLL") 
  If psapi
    CompilerIf #PB_Compiler_Unicode
      *F=GetFunction(psapi,"GetModuleFileNameExW")
    CompilerElse
      *F=GetFunction(psapi,"GetModuleFileNameExA")
    CompilerEndIf 
    If *F 
      CallFunctionFast(*F,hProcess,0,@Name,#MAX_PATH ) 
    Else 
      Debug "Fonction non trouvé" 
      CloseLibrary(psapi) 
      ;End 
    EndIf 
  Else 
    Debug "Library non ouverte" 
    ;End 
  EndIf 
  ProcedureReturn Name 
EndProcedure 


ProcedureDLL.s PidToFileName(PID.i) 
  ProcedureReturn PidToFileName_internal(PID)
EndProcedure



;-- Le Programme --

Enumeration
  #Window_0
  #BT
EndEnumeration

Global NomFenetre$="Calculatrice" ; Ici tu entres le nom de la fenetre de rainmeter, 
Global NomExe$="calc.exe"
Global PIDduPROG
;moi je ne l'ai pas donc j'ai mis la calculette windows à la place


;-----La Procédure-------


Procedure OuvreOuFerme() ; By Ar-S
  ChercheFenetre=FindWindow_(0,NomFenetre$) ; Cherche le Handle de la fenêtre
  Debug "Handle de la fenêtre :" +Str(ChercheFenetre)
  If ChercheFenetre=0 ; Si la fenêtre n'a pas été trouvée
    Debug "Programme non ouvert donc on l'ouvre :"+ProgAfermer$
    RunProgram("C:\windows\system32\calc.exe") ; On lance le programme
    PIDduPROG=GetPidProcess(NomExe$) ; On cherche le numéro qui lui est attribué
    Debug "PID Du Programme :"+Str(PIDduPROG)
  Else
    ProgAfermer$=HandleToFileName(ChercheFenetre) ; 
    Debug "Programme a fermer :"+ProgAfermer$
    PIDduPROG=GetPidProcess(NomExe$) ; ; On cherche le numéro qui lui est attribué
    KillProcess(PIDduPROG) ; Sinon On tue le programme
    Debug KillProcess(PIDduPROG)
    
  EndIf
EndProcedure
  

;----- lancement du programme avec un seul bouton :) ------

If OpenWindow(#Window_0, 450, 200, 194, 46, "OpenClose", #PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered)
  ButtonGadget(#BT, 5, 5, 180, 35, "1 Bouton suffit")
  
  
  ;{- La Boucle d'évenements
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #BT
            OuvreOuFerme() ; ça Roxe ?
        EndSelect
        
      Case #PB_Event_CloseWindow
        Select EventWindow()
          Case #Window_0
            CloseWindow(#Window_0)
            Break
        EndSelect
    EndSelect
  ForEver
EndIf


Re: Fermeture programme déjà lancé

Publié : lun. 22/mars/2010 16:56
par DarkIchigo
Merci beaucoup pour ton aide, mais quand je test ton programme ca ne ferme jamais la calc, ca en ouvre toujours un autre ^^

Edit : Après une bonne minute a étudier tout ton code dans tous les sens je viens de tilter, mon Windows est en Anglais => Calculator... :oops:

Re: Fermeture programme déjà lancé

Publié : lun. 22/mars/2010 17:19
par Ar-S
DarkIchigo a écrit : Après une bonne minute a étudier tout ton code dans tous les sens je viens de tilter, mon Windows est en Anglais => Calculator... :oops:
Forcement :mrgreen:

Re: Fermeture programme déjà lancé [RESOLU]

Publié : lun. 22/mars/2010 20:21
par DarkIchigo
Je viens de me rendre compte que en fait ca va pas marcher pour Rainmeter, simplement car il n'as pas de fenêtre principale, c'est un peu comme les widget Yahoo.

Comment fait du coup? :D

Re: Fermeture programme déjà lancé

Publié : lun. 22/mars/2010 20:49
par Ar-S
Il y a bien un nom dans le gestionnaire de taches lorsque tu fais ctrl alt sup ?

Re: Fermeture programme déjà lancé

Publié : lun. 22/mars/2010 20:53
par cha0s
au lieu de lancer Rainmeter au démarrage tu peut lancer ton programme qui va lancer a son tour Rainmeter. Grâce a ceci tu peut récupérer le handle de ce dernier.

Code : Tout sélectionner

HANDLE = RunProgram("C:\Program Files\Rainmeter\Rainmeter.exe");
;//Fermeture
CloseProgram(HANDLE);
Pas besoin d'aller chercher plus loin ! Je te conseille de regarder la doc partie "process".

Re: Fermeture programme déjà lancé

Publié : lun. 22/mars/2010 20:54
par DarkIchigo
Rainmeter.exe | Rainmeter

Re: Fermeture programme déjà lancé

Publié : lun. 22/mars/2010 20:58
par DarkIchigo
J'y avais pensé chaOs mais étant chiant de nature je préfère l'autre solution car ca m'intersse de pouvoir fermer un programme déjà lancé :D

mais merci quand même^^

Par contre en récupérant ton code tel quel ca ne marche plus chez moi (Windows Se7en x64)
pourtant installé la version x64 de la lib Droopy.
au moment de fermer le programme il m'affiche son Handle dans le debug mais rien ne se passe, et si je re-clic il n'ouvre rien de plus cette fois ci.
Par contre il l'ouvre bien la première fois.

Re: Fermeture programme déjà lancé

Publié : mar. 23/mars/2010 2:23
par Ar-S
Je suis sous Xp32 je peux pas te dire.

Re: Fermeture programme déjà lancé

Publié : mar. 23/mars/2010 9:55
par DarkIchigo
Bon de retour sur XP voila ce que m'affiche le Debug quand j'essaye de le faire marcher avec Rainmeter.

Code : Tout sélectionner

Handle de la fenêtre :0
Programme non ouvert donc on l'ouvre :
PID Du Programme :1828
Handle de la fenêtre :0
Programme non ouvert donc on l'ouvre :
PID Du Programme :3936
je pense que pour ce programme il faut contourner le pb du Handle de la fenetre et directement appliquer le kill si on a le PID.

Qu'en penses tu?

Re: Fermeture programme déjà lancé

Publié : mar. 23/mars/2010 10:55
par Ar-S
Faut je j'essaye avec le soft,
c'est celui ci ?
http://www.clubic.com/telecharger-fiche ... meter.html

Re: Fermeture programme déjà lancé

Publié : mar. 23/mars/2010 11:33
par Ar-S
Bon j'ai viré l'utilisation du nom de la fenêtre,
ça marche chez moi. La procédure est encore plus simple. :)

Code : Tout sélectionner

; Lanceur/killer de Rainmeter by Ar-S - PB 4.41
; Nécessite la Droopy Libs ou les composants
; - RegGetValue() , SearchProcess(), GetPIDProcess() , KillProcess()

;-- Le Programme --

Enumeration
  #Window_0 : #BT
EndEnumeration

Global NomExe$="Rainmeter.exe"
Global CheminProg$ 
Global PIDduPROG

CleProg$="HKEY_LOCAL_MACHINE\SOFTWARE\Rainmeter" ; Sous XP la clé indiquant le chemin est ici, modifie si sous 7 ce n'est pas au même endroit
ValProg$="" ; Valeur par defaut (pas de nom)
CheminProg$=RegGetValue(CleProg$,"",".")
CheminProg$+"\"+NomExe$ ; On trouve le chemin complet de l'exe directement dans le registre
Debug CheminProg$

;-----La Procédure-------

Procedure OuvreOuFerme() ; By Ar-S
  If SearchProcess(NomExe$)
    Debug "Trouvé donc on le ferme"
    PIDduPROG=GetPidProcess(NomExe$) ; ; On cherche le numéro qui lui est attribué
    KillProcess(PIDduPROG) ; Sinon On tue le programme
  Else
    Debug "Non trouvé donc on l'ouvre"
    RunProgram(CheminProg$) ; On lance le programme
  EndIf
EndProcedure
  

;----- lancement du programme avec un seul bouton :) ------

If OpenWindow(#Window_0, 450, 200, 194, 46, "OpenClose", #PB_Window_MinimizeGadget|#PB_Window_TitleBar|#PB_Window_ScreenCentered)
  ButtonGadget(#BT, 5, 5, 180, 35, "1 Bouton suffit")
  
  
  ;{- La Boucle d'évenements
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #BT
            OuvreOuFerme() ; ça RoxXxe cette fois :) ?
        EndSelect
        
      Case #PB_Event_CloseWindow
        Select EventWindow()
          Case #Window_0
            CloseWindow(#Window_0)
            Break
        EndSelect
    EndSelect
  ForEver
EndIf

Re: Fermeture programme déjà lancé

Publié : mar. 23/mars/2010 11:35
par DarkIchigo
Terrible, Merci :D