Newsgroup: it.comp.lang.delphi
Titolo: Nome del file exe associato ad una finestra ?

Salve a tutti!
Sto provando da qualche giorno a trovare un sistema per ricavare il nome del
file eseguibile dall'handle della finestra,
ma non riesco a farlo se non per la mia applicazione.
Per evitare equivoci spiego bene (spero) il problema e i tentativi che ho
fatto :
io vorrei sapere che file exe corrisponde ad una finestra il cui handle
trovo in runtime.
Ho provato la GetModuleFileName ... ma come hinstance non so cosa dargli.
Tra l'altro...
io ho provato anche qualcosa tipo :
 for i := 0 to 1000000 do begin// i in realtà variava da hinstance-500000 a
hinstance + 500000
  R := getmodulefilename (i, @c, sizeof(c));  // dove c è il classico array
di caratteri.
 if R <> 0 then  // then fa vedere cos'hai copiato in c.
end;
Però la funzione fallisce sempre tranne per i = hinstance. Quindi mi è sorto
il dubbio che :
1. La getmodulefilename non sia la funzione che cerco.
2. oppure funzioni solo per i programmi/librerie aperti dalla mia
applicazione (il che mi riporta al punto 1... :( )
In definitiva ... Come posso fare per ottenere il nome del file exe
proprietario di una finestra di cui conosco l'handle?
Grazie  in anticipo a tutti. CIAO!!   Davide DG.

Davide DG ha scritto nel messaggio...
[SNIP]
Se sei sotto NT/Win2K puoi usare agevolmente la GetModuleFileNameEx, dopo
aver recuperato l'handle del processo con una GetWindowThreadProcessID unita
ad una OpenProcess (NB: gli handle che vengono ritornati da alcune funzioni
sono dei pseudo-handle, ciò hanno significato solo all'interno del processo
chiamante, la OpenProcess permette di scavalcare questa "limitazione"...)
Non ricordo con precisione (sviluppo poco sotto NT), potresti aver bisogno
di una EnumProcessModules e dover fare la GetModuleFileNameEx su un handle
di quelli...
Altrimenti (ovvero se sei sotto Win9X) dovrai fare così:
con la GetWindowThreadProcessID ottieni il PID, con le ToolHelp ti recuperi
una lista dei PID attualmente attivi e confronti il PID che hai con quelli
della lista (visto che cmq, le toolHelp ti ritornano pure il path
dell'EXE...)
Puoi seguire questa seconda anche sotto NT ma dovrai sfruttare le PSAPI
invece delle ToolHelp32...
Ciao :-)
Ps: sono un po' arrugginito ultimamente sulle API di Win32, ma se non
ricordo male avevo trovato una scappatoia decisamente carina (sotto Win9X),
se la ritrovo la posto ma non vi prometto nulla ;-)
--
Andrea Magni
E-Mail: 
ama...@energy.it

Se sei sotto NT/Win2K puoi usare agevolmente la GetModuleFileNameEx
Scusa, ma perchč non č documentata nel mio SDK? E' forse un API dell'ultima
ora, ovvero devo aggiornare il mio SDK?
Per quel che riguarda le ToolHelp ho provato a ricercare Create32bitSnapShot
(come dicesti in una vecchia mail) ma non mi ha trovato nulla.
Ciao a tutti
--
- Carlo -
BSSoftware Tips Mailing-List Support

Ciao!! Innanzitutto grazie mille per la risposta !!
Ora ... Cosa sono le toolhelp32 e le psapi ? <<--
Sě sě lo so che potrei sforzarmi un po' di piů e cercare nell'help o in
internet .. ma
pietŕ ... č tardi, domani mi sveglio presto per andare al FuturShow (ghhh !!
:-))
e ultimamente sono un po' lazy (write? ... ;-) )
Ciaooooooooooooooooooooooooooooooooooooooooooooooooooooooo [stack overflow]
!!
Davide DG.

 Mi sorge il dubbio che questa GetModuleFileName sia inutile.
... anch'io ho avuto la medesima impressione ... o piuttosto mi sapeva di
funzione
per ricavare da handle INTERNI al processo chiamante i nomi di eventuali
moduli
caricati in run-time ... in altre parole qualcosa che ad un programmatore
visuale non
"dovrebbe" (frecciatina verso alcune decisioni nell'help della borland...)
interessare...
Ciao!!! Davide DG.

 (come dicesti in una vecchia mail) ma non mi ha trovato nulla.
CreateToolhelp32Snapshot, unit tlhelp32 ..
C'è un esempio in C nell'SDK (win32.hlp) ma dovrai sfruttare il "Trova"
anzichè l' "indice" ...
Ciao :-)
--
(¯`·.¸¸.·´¯`·.¸¸.-> Andrea <-.¸¸.·´¯`·.¸¸.·´¯)
AntiSpam: rimuovere il trattino basso dall'indirizzo per rispondere
AntiSpam: remove the underscore from the e-mail address to reply

 pietà ... è tardi, domani mi sveglio presto per andare al FuturShow (ghhh
!!
Beato te...


Ok ... ho provato con :
var A: thandle;
var P : tagMODULEENTRY32;  // ho provato anche coi process...
var c : array[0..255] of char;
procedure TForm1.FormCreate(Sender: TObject);
    begin   A := CreateToolhelp32Snapshot (TH32CS_SNAPALL,0);   end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
      begin  CloseHandle (A);  end;
Procedure TForm1.Button1Click(Sender: TObject);
begin
   module32next (a,p);  // o process32next, cambiando il tipo di P.
   GetModuleFilename (p.th32ModuleID,@c,sizeof(c));
   Caption := c;
end;
Ma la caption coincide con Application.Exename.
Penso di aver sbagliato il parametro di CreateToolhelp32Snapshot ... perchè
al posto di 0 non so cosa passargli ...
Chi mi viene in aiuto ?
Thx very muchhh, Davide DG.

Ciao a tutti !! Sono felice perchè ho risolto sto problema... finalmente!!
Innanzitutto grazie ad Andrea Magni (come al solito ...!!! :)  ) che mi ha
"svelato" l'esistenza
della unit tlhelp32 ... ma non potevano farci anche l'help ?
La funzione risultante è :
// Uses tlhelp32;
Type TStringArray = Array of string;
         PStringArray = ^TStringArray;
CONST
 _GM_ALL = $00000000;
 _GM_EXE = $00000001;
FUNCTION GetModulesFromWindowHandle(WH: THandle; flags : cardinal; Modules :
PStringArray): Integer;
Var pid,snapshot : cardinal;
      i : integer;
      ME : TModuleEntry32;
      b : boolean;
begin
 pid := 0;
 result := 0;
 GetWindowThreadProcessID (WH, @pid);
 if pid=0 then exit;
 snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPALL, pid);
 if Module32First (snapshot,ME) then begin
    i := 0;
    Repeat
      if   (      (flags = _gm_all)
             OR   ( (flags = _gm_exe) and
(lowercase(ExtractFileExt(me.szExePath))= '.exe') ))
         then begin
             setlength ( modules^, i+1 );
             modules^[i] := me.szExePath;
             inc(i);
         end;
      b := Module32Next (snapshot,me);
    Until not b;
 end else i := 0;
 CloseHandle (snapshot);
 Result := i;
End;
Ed eccone un esempio :
Procedure TForm1.Button1Click(Sender: TObject);
    var ss : array of string;
     j : integer;
Begin
 for j := 0 to GetModulesFromWindowHandle ( handle, _gm_exe, @ss) -1 do
   Memo1.lines.add (ss[i]);
End;
Grazie a tutti & CIAOOOOO !!! ;-))))))
Davide DG.

 ma non potevano farci anche l'help ?
Ma se c'è perfino un esempio !?!
Ma:
1) perchè scorri i moduli e non i processi?
2) perchè hai strutturato il tutto come se una finestra potesse essere stata
creata da + processi? ;-)
Function GetProcessPath(hwnd: HWND):String;
var
 hSnapShot, PID : cardinal;
 Processo : TPROCESSENTRY32;
 bSuccess : Boolean;
begin
 GetWindowThreadProcessID(hwnd,@PID);
 hSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
 if hSnapShot = $FFFFFF
   then raise Exception.Create('Impossibile creare uno SnapShot dei
processi');
 Processo.dwSize := sizeof(Processo);
 bSuccess := Process32First(hSnapShot, Processo);
 while bSuccess do
  begin
  if Processo.th32ProcessID=PID
    then result := Processo.szExeFile;
  bSuccess := Process32Next(hSnapShot, Processo)
  end;
 CloseHandle(hSnapShot);
End;
Mi sembra + lineare...
Ps: ti ricordo che cmq sotto NT questo codice non ha senso...


 (¯`·.¸¸.·´¯`·.¸¸.-> Andrea <-.¸¸.·´¯`·.¸¸.·´¯)
(_.·´¯`·.¸¸.·´¯`·-> Davide DG  <-·´¯`·.¸¸.·´¯`·._)        :)) hihi !
Ciao!! ;-)  Davide DG.