Récuperer chemin+nom d'executable à partir du handle

Programmation d'applications complexes
dlolo
Messages : 118
Inscription : ven. 18/févr./2005 16:29

Récuperer chemin+nom d'executable à partir du handle

Message par dlolo »

Salut,

tout est dans le titre, je cherche à récuperer le chemin et le nom de l'executable depuis un handle de fenêtre.

J'imagine qu'il faille passer par les API Windows mais je ne sais pas lesquelles.

J'ai trouvé une partie de ce que cherche (voir en dessous) mais ce code ne me donne que le nom de l'executable, sans le chemin !

Code : Tout sélectionner

; English forum: http://purebasic.myforums.net/viewtopic.php?t=8555&highlight= 
; Author: Hi-Toro 
; Date: 30. November 2003 

; ----------------------------------------------------------------------------- 
; Public domain -- Hi-Toro 2003 
; ----------------------------------------------------------------------------- 
; Return a window's process name from its handle... 
; ----------------------------------------------------------------------------- 

; IMPORTANT! You must paste the following section of code (from here to the 
; demo section) at the top of your code, AND paste the part at the bottom 
; (the 'GetProcessList' sub-routine) at the bottom of your code. The reason the 
; sub-routine is required (rather than a procedure) is that the Win32 function 
; 'Process32Next' seems to fail on Windows 9x when called from inside a procedure... 

; Note that you should always call 'GetProcessList' before trying to retrieve a window's process name... 

; ----------------------------------------------------------------------------- 
; Paste at top of your code... 
; ----------------------------------------------------------------------------- 

#TH32CS_SNAPHEAPLIST = $1 
#TH32CS_SNAPPROCESS = $2 
#TH32CS_SNAPTHREAD = $4 
#TH32CS_SNAPMODULE = $8 
#TH32CS_SNAPALL = #TH32CS_SNAPHEAPLIST | #TH32CS_SNAPPROCESS | #TH32CS_SNAPTHREAD | #TH32CS_SNAPMODULE 
#TH32CS_INHERIT = $80000000 
#INVALID_HANDLE_VALUE = -1 
#MAX_PATH = 260 
#PROCESS32LIB = 9999 

Structure PROCESSENTRY32 
  dwSize.l 
  cntUsage.l 
  th32ProcessID.l 
  *th32DefaultHeapID.l 
  th32ModuleID.l 
  cntThreads.l 
  th32ParentProcessID.l 
  pcPriClassBase.l 
  dwFlags.l 
  szExeFile.b [#MAX_PATH] 
EndStructure 

; List used to store processes on 'Gosub GetProcessList'... 

NewList Process32.PROCESSENTRY32 () 

; Returns process name from window handle... 
; IMPORTANT! You should 'Gosub GetProcessList' before calling this! 

Procedure.s FindWindowProcessName (window) 
  ResetList (Process32 ()) 
  While NextElement (Process32 ()) 
    GetWindowThreadProcessId_ (window, @pid) 
    If pid = Process32 ()\th32ProcessID 
      exe$ = GetFilePart (PeekS (@Process32 ()\szExeFile)) 
      LastElement (Process32 ()) 
    EndIf 
  Wend 
  ProcedureReturn exe$ 
EndProcedure 

; Returns Process ID from window handle... 

Procedure.l FindWindowProcessID (window) 
  GetWindowThreadProcessId_ (window, @pid) 
  ProcedureReturn pid 
EndProcedure 

; ----------------------------------------------------------------------------- 
; D E M O... 
; ----------------------------------------------------------------------------- 

window = OpenWindow (0, 0, 0, 320, 200, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Test window") 

; Update every 100 ms... 

SetTimer_ (WindowID (), 0, 100, 0) 

Repeat 
  Select WaitWindowEvent () 
    Case #PB_Event_CloseWindow 
      End 
    Case #WM_TIMER 
      ; Get process list... 
      Gosub GetProcessList 
      ; Get window under mouse position... 
      GetCursorPos_ (@p.POINT) 
      over = WindowFromPoint_ (p\x, p\y) 
      ; Find its name and set this window's title to it... 
      proc$ = FindWindowProcessName (over) 
      SetWindowText_ (window, proc$) 
  EndSelect 
ForEver 

; ----------------------------------------------------------------------------- 
; Paste at bottom of your code... 
; ----------------------------------------------------------------------------- 

End ; Leave this here! 

GetProcessList: 

ClearList (Process32 ()) 

    ; Add processes to Process32 () list... 

If OpenLibrary (#PROCESS32LIB, "kernel32.dll") 
  
  snap = CallFunction (#PROCESS32LIB, "CreateToolhelp32Snapshot", #TH32CS_SNAPPROCESS, 0) 
  
  If snap 
    
    DefType.PROCESSENTRY32 Proc32 
    Proc32\dwSize = SizeOf (PROCESSENTRY32) 
    
    If CallFunction (#PROCESS32LIB, "Process32First", snap, @Proc32) 
      
      AddElement (Process32 ()) 
      CopyMemory (@Proc32, @Process32 (), SizeOf (PROCESSENTRY32)) 
      
      While CallFunction (#PROCESS32LIB, "Process32Next", snap, @Proc32) 
        AddElement (Process32 ()) 
        CopyMemory (@Proc32, @Process32 (), SizeOf (PROCESSENTRY32)) 
      Wend 
      
    EndIf    
    CloseHandle_ (snap) 
    
  EndIf 
  
  CloseLibrary (#PROCESS32LIB) 
  
EndIf 

Return 
la ligne importante :

Code : Tout sélectionner

exe$ = GetFilePart (PeekS (@Process32 ()\szExeFile)) 
J'ai bien essayé de remplacer GetFilePart par GetPathPart mais ça ne fonctionne pas. En fait, La variable szExeFile de la structure Process32 ne contient que le nom de l'exe, sans le chemin.

Merci d'avance.
dlolo
Messages : 118
Inscription : ven. 18/févr./2005 16:29

Message par dlolo »

...
Coolman
Messages : 432
Inscription : sam. 01/janv./2005 16:07

Message par Coolman »

c'est peut etre ca que tu cherches :

Procedure.s GetExePath()
NomExe.s=Space(255) : Chemin.s=""
; Ici recupere le chemin et le nom du fichier exe
GetModuleFileName_(0, @NomExe, 255)
; Ici recupere uniquement le chemin
Chemin=GetPathPart(NomExe)
ProcedureReturn Chemin
EndProcedure

CheminEXE$=GetExePath()
Debug CheminEXE$

je dois avoir recuperé ca dans les sources de droopy je crois, a ce propos bravo droopy de fournir les sources, perso je zappes toutes les libs qui ne comportent pas les sources...
dlolo
Messages : 118
Inscription : ven. 18/févr./2005 16:29

Message par dlolo »

euh :?: Oui presque, je veux obtenir le nom et le chemin de l'exe qui a ouvert une fenêtre. Donc par son handle.

Dans ton exemple, j'obtiens bien un chemin d'exe mais du programme 'actuel'.

Mon but est d'obtenir une liste des programmes en cours d'execution. Avec le chemin et le nom de l'exe. Pour ça, je passe par les fenêtres ouvertes et leurs handles.

En tous cas, merci de la réponse, je vais chercher du côté du GetModuleFileName_.
Coolman
Messages : 432
Inscription : sam. 01/janv./2005 16:07

Message par Coolman »

Pour ca j'utilise perso :

http://www.sysinternals.com/

Process Explorer
dlolo
Messages : 118
Inscription : ven. 18/févr./2005 16:29

Message par dlolo »

Ca a l'air intéressant mais j'ai besoin de résoudre ce problème pour ensuite faire une application !

Mais je crois que je suis sur la bonne voie,

A suivre...
dlolo
Messages : 118
Inscription : ven. 18/févr./2005 16:29

Message par dlolo »

Bon ok j'ai réussi, ça ne fonctionne pas sur Win98 car j'utilise la dll PSAPI.DLL pour la fonction GetModuleFileNameEx.

Voici le code, c'est une énumeration des fenêtres ouvertes (grace à la procedure du soldat inconnu) et pour chaque fenêtre ouverte je récupère le nom et le chemin de l'exe.

Code : Tout sélectionner

#PROCESS_ALL_ACCESS=$01F0FFF
#MAX_PATH=$0104

Procedure.s GetExePath(hWnd.l)
  pid.l=0
  GetWindowThreadProcessId_( hWnd, @pid )
  hProcess.l = OpenProcess_( #PROCESS_ALL_ACCESS, 0, pid ); 
  Name.s=Space(256)
  
  If OpenLibrary(0,"PSAPI.DLL")
    *F=IsFunction(0,"GetModuleFileNameExA")
    If *F
      CallFunctionFast(*F,hProcess,0,@Name,#MAX_PATH )
    Else
      Debug "Fonction non trouvé"
      CloseLibrary(0)
      End
    EndIf
  Else
    Debug "Library non ouverte"
    End
  EndIf
  ProcedureReturn Name
EndProcedure

Procedure FindWindowExeName()
  
  hWnd.l = FindWindow_( 0, 0 )
  
  While hWnd <> 0 
    If GetWindowLong_(hWnd, #GWL_STYLE) & #WS_VISIBLE = #WS_VISIBLE 
      If GetWindowLong_(hWnd, #GWL_EXSTYLE) & #WS_EX_TOOLWINDOW <> #WS_EX_TOOLWINDOW 
        txt.s = Space(256) 
        GetWindowText_(hWnd,@txt,256) 
        
        If txt <> ""
          
          Debug txt +" - " + GetExePath(hWnd)
          
        EndIf 
      EndIf 
    EndIf 
    hWnd = GetWindow_(hWnd, #GW_HWNDNEXT) 
  Wend
EndProcedure

FindWindowExeName()
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ha bein ! l'air de rien c'est pratique ton truc !! :D

Merci .... :D
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

j'ai des questions là dessus (je m'y intéresse tout juste). J'ai viré le getfilepart qui semblait poser problème à dlolo et sur mon windows 98 ca fonctionne nickel... Et chez vous ?

Code : Tout sélectionner

; English forum: http://purebasic.myforums.net/viewtopic.php?t=8555&highlight=
; Author: Hi-Toro
; Date: 30. November 2003

; -----------------------------------------------------------------------------
; Public domain -- Hi-Toro 2003
; -----------------------------------------------------------------------------
; Return a window's process name from its handle...
; -----------------------------------------------------------------------------

; IMPORTANT! You must paste the following section of code (from here to the
; demo section) at the top of your code, AND paste the part at the bottom
; (the 'GetProcessList' sub-routine) at the bottom of your code. The reason the
; sub-routine is required (rather than a procedure) is that the Win32 function
; 'Process32Next' seems to fail on Windows 9x when called from inside a procedure...

; Note that you should always call 'GetProcessList' before trying to retrieve a window's process name...

; -----------------------------------------------------------------------------
; Paste at top of your code...
; -----------------------------------------------------------------------------

#TH32CS_SNAPHEAPLIST = $1
#TH32CS_SNAPPROCESS = $2
#TH32CS_SNAPTHREAD = $4
#TH32CS_SNAPMODULE = $8
#TH32CS_SNAPALL = #TH32CS_SNAPHEAPLIST | #TH32CS_SNAPPROCESS | #TH32CS_SNAPTHREAD | #TH32CS_SNAPMODULE
#TH32CS_INHERIT = $80000000
#INVALID_HANDLE_VALUE = -1
#MAX_PATH = 260
#PROCESS32LIB = 9999

Structure PROCESSENTRY32
  dwSize.l
  cntUsage.l
  th32ProcessID.l
  *th32DefaultHeapID.l
  th32ModuleID.l
  cntThreads.l
  th32ParentProcessID.l
  pcPriClassBase.l
  dwFlags.l
  szExeFile.b [#MAX_PATH]
EndStructure

; List used to store processes on 'Gosub GetProcessList'...

NewList Process32.PROCESSENTRY32 ()

; Returns process name from window handle...
; IMPORTANT! You should 'Gosub GetProcessList' before calling this!

Procedure.s FindWindowProcessName (window)
  ResetList (Process32 ())
  While NextElement (Process32 ())
    GetWindowThreadProcessId_ (window, @pid)
    If pid = Process32 ()\th32ProcessID
      exe$ = PeekS (@Process32 ()\szExeFile)
      LastElement (Process32 ())
    EndIf
  Wend
  ProcedureReturn exe$
EndProcedure

; Returns Process ID from window handle...

Procedure.l FindWindowProcessID (window)
  GetWindowThreadProcessId_ (window, @pid)
  ProcedureReturn pid
EndProcedure

; -----------------------------------------------------------------------------
; D E M O...
; -----------------------------------------------------------------------------

window = OpenWindow (0, 0, 0, 320, 200, #PB_Window_SystemMenu | #PB_Window_ScreenCentered, "Process32")
CreateGadgetList( window )
TextGadget(0, 10, 10, 100, 24, "La souris pointe sur :")
TextGadget(1, 10, 34, 300, 48, "")

; Update every 100 ms...

SetTimer_(WindowID (), 0, 100, 0)

Repeat
  Select WaitWindowEvent ()
    Case #PB_Event_CloseWindow
      End
    Case #WM_TIMER
      ; Get process list...
      Gosub GetProcessList
      ; Get window under mouse position...
      GetCursorPos_ (@p.POINT)
      over = WindowFromPoint_(p\x, p\y)
      ; Find its name and set this window's title to it...
      proc$ = FindWindowProcessName (over)
      SetGadgetText(1, proc$)
  EndSelect
ForEver

; -----------------------------------------------------------------------------
; Paste at bottom of your code...
; -----------------------------------------------------------------------------

End ; Leave this here!

GetProcessList:

ClearList (Process32 ())

    ; Add processes to Process32 () list...

If OpenLibrary (#PROCESS32LIB, "kernel32.dll")
 
  snap = CallFunction (#PROCESS32LIB, "CreateToolhelp32Snapshot", #TH32CS_SNAPPROCESS, 0)
 
  If snap
   
    DefType.PROCESSENTRY32 Proc32
    Proc32\dwSize = SizeOf (PROCESSENTRY32)
   
    If CallFunction (#PROCESS32LIB, "Process32First", snap, @Proc32)
     
      AddElement (Process32 ())
      CopyMemory (@Proc32, @Process32 (), SizeOf (PROCESSENTRY32))
     
      While CallFunction (#PROCESS32LIB, "Process32Next", snap, @Proc32)
        AddElement (Process32 ())
        CopyMemory (@Proc32, @Process32 (), SizeOf (PROCESSENTRY32))
      Wend
     
    EndIf   
    CloseHandle_ (snap)
   
  EndIf
 
  CloseLibrary (#PROCESS32LIB)
 
EndIf

Return
Dri
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

sur XP pro , ça marche bien ! :D
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

donc t'as bien le chemin et le nom de l'exe ?

Dri
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ben non j'ai juste le nom de l'exe pointé !!

tu dit
J'ai viré le getfilepart qui semblait poser problème à dlolo
comment veut tu que j'ai le chemin puisque dans le code que tu donne il n'y a aucune procedure qui traite de ce sujet !! :D

je suppose que c'etait la procedure que tu a viré non ? 8O
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

bah chez moi j'ai bien le chemin ET l'exe :-?
c'est dommage qu'avec XP ca ne soit pas le cas

Dri
Avatar de l’utilisateur
Jacobus
Messages : 1559
Inscription : mar. 06/avr./2004 10:35
Contact :

Message par Jacobus »

Je remonte ce vieux topic histoire de savoir si quelqu'un connaît le moyen de récupérer le chemin complet d'un exe par son nom seul?

J'ai remis au goût du jour les deux codes initiaux (v 4.10)

Trouver le chemin complet d'un exe grâce à la fenêtre ouverte:

Code : Tout sélectionner

#PROCESS_ALL_ACCESS=$01F0FFF 
#MAX_PATH=$0104 

Procedure.s GetExePath(hWnd.l) 
  pid.l=0 
  GetWindowThreadProcessId_( hWnd, @pid ) 
  hProcess.l = OpenProcess_( #PROCESS_ALL_ACCESS, 0, pid ); 
  Name.s=Space(256) 
  
  If OpenLibrary(0,"PSAPI.DLL") 
    *F=GetFunction(0,"GetModuleFileNameExA") 
    If *F 
      CallFunctionFast(*F,hProcess,0,@Name,#MAX_PATH ) 
    Else 
      Debug "Fonction non trouvé" 
      CloseLibrary(0) 
      End 
    EndIf 
  Else 
    Debug "Library non ouverte" 
    End 
  EndIf 
  ProcedureReturn Name 
EndProcedure 

Procedure FindWindowExeName() 
  
  hWnd.l = FindWindow_( 0, 0 ) 
  
  While hWnd <> 0 
    If GetWindowLong_(hWnd, #GWL_STYLE) & #WS_VISIBLE = #WS_VISIBLE 
      If GetWindowLong_(hWnd, #GWL_EXSTYLE) & #WS_EX_TOOLWINDOW <> #WS_EX_TOOLWINDOW 
        txt.s = Space(256) 
        GetWindowText_(hWnd,@txt,256) 
        
        If txt <> "" 
          
          Debug txt +" - " + GetExePath(hWnd) 
          
        EndIf 
      EndIf 
    EndIf 
    hWnd = GetWindow_(hWnd, #GW_HWNDNEXT) 
  Wend 
EndProcedure 

FindWindowExeName() 


La souris pointe sur...

Code : Tout sélectionner

; English forum: http://purebasic.myforums.net/viewtopic.php?t=8555&highlight= 
; Author: Hi-Toro 
; Date: 30. November 2003 

; ----------------------------------------------------------------------------- 
; Public domain -- Hi-Toro 2003 
; ----------------------------------------------------------------------------- 
; Return a window's process name from its handle... 
; ----------------------------------------------------------------------------- 

; IMPORTANT! You must paste the following section of code (from here to the 
; demo section) at the top of your code, AND paste the part at the bottom 
; (the 'GetProcessList' sub-routine) at the bottom of your code. The reason the 
; sub-routine is required (rather than a procedure) is that the Win32 function 
; 'Process32Next' seems to fail on Windows 9x when called from inside a procedure... 

; Note that you should always call 'GetProcessList' before trying to retrieve a window's process name... 

; ----------------------------------------------------------------------------- 
; Paste at top of your code... 
; ----------------------------------------------------------------------------- 

#TH32CS_SNAPHEAPLIST = $1 
#TH32CS_SNAPPROCESS = $2 
#TH32CS_SNAPTHREAD = $4 
#TH32CS_SNAPMODULE = $8 
#TH32CS_SNAPALL = #TH32CS_SNAPHEAPLIST | #TH32CS_SNAPPROCESS | #TH32CS_SNAPTHREAD | #TH32CS_SNAPMODULE 
#TH32CS_INHERIT = $80000000 
#INVALID_HANDLE_VALUE = -1 
#MAX_PATH = 260 
#PROCESS32LIB = 9999 

; Structure PROCESSENTRY32 
;   dwSize.l 
;   cntUsage.l 
;   th32ProcessID.l 
;   *th32DefaultHeapID.l 
;   th32ModuleID.l 
;   cntThreads.l 
;   th32ParentProcessID.l 
;   pcPriClassBase.l 
;   dwFlags.l 
;   szExeFile.b [#MAX_PATH] 
; EndStructure 
; 
; ; List used to store processes on 'Gosub GetProcessList'... 
; 
Global NewList Process32.PROCESSENTRY32 () 

; Returns process name from window handle... 
; IMPORTANT! You should 'Gosub GetProcessList' before calling this! 

Procedure.s FindWindowProcessName (window) 
  ResetList (Process32 ()) 
  While NextElement (Process32 ()) 
    GetWindowThreadProcessId_ (window, @pid) 
    If pid = Process32 ()\th32ProcessID 
      exe$ = PeekS (@Process32 ()\szExeFile) 
      LastElement (Process32 ()) 
    EndIf 
  Wend 
  ProcedureReturn exe$ 
EndProcedure 

; Returns Process ID from window handle... 

Procedure.l FindWindowProcessID (window) 
  GetWindowThreadProcessId_ (window, @pid) 
  ProcedureReturn pid 
EndProcedure 

; ----------------------------------------------------------------------------- 
; D E M O... 
; ----------------------------------------------------------------------------- 

window = OpenWindow (0, 0, 0, 320, 200, "Process32", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) 
CreateGadgetList( window ) 
TextGadget(0, 10, 10, 100, 24, "La souris pointe sur :") 
TextGadget(1, 10, 34, 300, 48, "") 

; Update every 100 ms... 

SetTimer_(WindowID (0), 0, 100, 0) 

Repeat 
  Select WaitWindowEvent () 
    Case #PB_Event_CloseWindow 
      End 
    Case #WM_TIMER 
      ; Get process list... 
      Gosub GetProcessList 
      ; Get window under mouse position... 
      GetCursorPos_ (@p.POINT) 
      over = WindowFromPoint_(p\x, p\y) 
      ; Find its name and set this window's title to it... 
      proc$ = FindWindowProcessName (over) 
      SetGadgetText(1, proc$) 
  EndSelect 
ForEver 

; ----------------------------------------------------------------------------- 
; Paste at bottom of your code... 
; ----------------------------------------------------------------------------- 

End ; Leave this here! 

GetProcessList: 

ClearList (Process32 ()) 

    ; Add processes to Process32 () list... 

If OpenLibrary (#PROCESS32LIB, "kernel32.dll") 
  
  snap = CallFunction (#PROCESS32LIB, "CreateToolhelp32Snapshot", #TH32CS_SNAPPROCESS, 0) 
  
  If snap 
    
    Define.PROCESSENTRY32 Proc32 
    Proc32\dwSize = SizeOf (PROCESSENTRY32) 
    
    If CallFunction (#PROCESS32LIB, "Process32First", snap, @Proc32) 
      
      AddElement (Process32 ()) 
      CopyMemory (@Proc32, @Process32 (), SizeOf (PROCESSENTRY32)) 
      
      While CallFunction (#PROCESS32LIB, "Process32Next", snap, @Proc32) 
        AddElement (Process32 ()) 
        CopyMemory (@Proc32, @Process32 (), SizeOf (PROCESSENTRY32)) 
      Wend 
      
    EndIf    
    CloseHandle_ (snap) 
    
  EndIf 
  
  CloseLibrary (#PROCESS32LIB) 
  
EndIf 

Return
Si vous avez une idée...
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

y doit y avoir un autre topic avec la solution parce que je me rapelle avoir réussi à concilier les windows 9X et NT

Dri
Répondre