Von PID oder hWnd auf den EXE-Namen schließen

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Tatsache... :o

Gibt's eigentlich auch eine neuere Version der WIN32.hlp? Und was ist dieses SDK, von dem Fluid Byte sprach?
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Beitrag von edel »

Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

Schon etwas älter, ich hole das aber mal wieder hoch, da ich auf http://www.vbarchiv.net/archiv/tipp_det ... p?pid=1018 eine Möglichkeit gefunden habe, Den Filenamen, der zu einen Fenster gehört zuverlässiger zu ermitteln als dies mit GetWindowModuleFilename geschieht, wo öfter kein Filename zurückgeliefert wird.
Ich habe das mal nach Purebasic umgesetzt:

Code: Alles auswählen

Prototype.l GetModuleFileNameEx(hProcess.l, hModule.l, *lpFilename, nSize)
Prototype.l EnumProcessModules(hProcess, *lphModule, cb, lpchNeeded)

Global GetModuleFileNameEx.GetModuleFileNameEx
Global EnumProcessModules.EnumProcessModules

Procedure.s GetEXEFromHandle(nHWnd.l = 0)
  
  Protected nProcID, nResult, nTemp, hProcess
  Protected sFile.s
  Dim lModules.l(200)
  
  
  ; ProcessID ermitteln
  If GetWindowThreadProcessId_(nHWnd, @nProcID) <> 0
    ; Prozess-Handle ermitteln
    hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, 0, nProcID)
    If hProcess <> 0
      ; Module des Prozess enumerieren
      nResult = EnumProcessModules(hProcess, @lModules(0), 200, @nTemp)
      If nResult <> 0
        ; Dateiname ermitteln
        sFile = Space(260)
        nResult = GetModuleFileNameEx(hProcess, 0, @sFile, Len(sFile))
        sFile = LCase(Left(sFile, nResult))
        
      EndIf
      
      ; Handle schließen
      CloseHandle_(hProcess)
    EndIf
  EndIf
  ProcedureReturn sFile
EndProcedure

If OpenLibrary(0, "psapi.dll")
	;Process Status Helper API einbinden
	GetModuleFileNameEx = GetFunction(0, "GetModuleFileNameExA")
	EnumProcessModules = GetFunction(0, "EnumProcessModules")
EndIf

;Hier Code einfügen

CloseLibrary(0)
Zuletzt geändert von Ligatur am 24.04.2007 15:46, insgesamt 1-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Etwas einfacher, sollte dasselbe bewirken :wink:

Code: Alles auswählen

Procedure.s GetEXEFromHandle(hWnd.l = 0)
  Protected Result.s, PID.l, handle.l, err.l
  Protected Entry.MODULEENTRY32
  
  If hWnd = 0 : hWnd = GetForegroundWindow_() : EndIf
  
  Entry\dwSize = SizeOf(MODULEENTRY32)
  GetWindowThreadProcessId_(hWnd, @PID)
  handle = CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE, PID)

  If handle
    err = Module32First_(handle, Entry)
    If err
       Result = PeekS(@Entry\szExePath)
    EndIf
    CloseHandle_(handle)
  EndIf  
  
  ProcedureReturn Result
EndProcedure

Debug GetEXEFromHandle()
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

@ts-soft:
Stimmt, deine Methode ist einfacher und bewirkt das selbe, ist aber wesentlich langsamr.

Code: Alles auswählen

Prototype.l GetModuleFileNameEx(hProcess.l, hModule.l, *lpFilename, nSize)
Prototype.l EnumProcessModules(hProcess, *lphModule, cb, lpchNeeded)

Global GetModuleFileNameEx.GetModuleFileNameEx
Global EnumProcessModules.EnumProcessModules

Procedure.s GetEXEFromHandle(nHWnd.l = 0)
  
  Protected nProcID, nResult, nTemp, hProcess
  Protected sFile.s
  Dim lModules.l(200)
  
  If nHwnd = 0
  	nHWnd = GetForegroundWindow_()
  EndIf
  
  ; ProcessID ermitteln
  If GetWindowThreadProcessId_(nHWnd, @nProcID) <> 0
    ; Prozess-Handle ermitteln
    hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, 0, nProcID)
    If hProcess <> 0
      ; Module des Prozess enumerieren
      nResult = EnumProcessModules(hProcess, @lModules(0), 200, @nTemp)
      If nResult <> 0
        ; Dateiname ermitteln
        sFile = Space(260)
        nResult = GetModuleFileNameEx(hProcess, 0, @sFile, Len(sFile))
        sFile = LCase(Left(sFile, nResult))
        
      EndIf
      
      ; Handle schließen
      CloseHandle_(hProcess)
    EndIf
  EndIf
  ProcedureReturn sFile
EndProcedure

If OpenLibrary(0, "psapi.dll")
	;Process Status Helper API einbinden
	GetModuleFileNameEx = GetFunction(0, "GetModuleFileNameExA")
	EnumProcessModules = GetFunction(0, "EnumProcessModules")
EndIf

st = ElapsedMilliseconds()
For i = 1 To 1000
	path.s = GetEXEFromHandle()
Next
sp = ElapsedMilliseconds() - st

MessageRequester(path, Str(sp))

CloseLibrary(0)

Code: Alles auswählen

Procedure.s GetEXEFromHandle(hWnd.l = 0) 
  Protected Result.s, PID.l, handle.l, err.l 
  Protected Entry.MODULEENTRY32 
  
  If hWnd = 0 : hWnd = GetForegroundWindow_() : EndIf 
  
  Entry\dwSize = SizeOf(MODULEENTRY32) 
  GetWindowThreadProcessId_(hWnd, @PID) 
  handle = CreateToolhelp32Snapshot_(#TH32CS_SNAPMODULE, PID) 

  If handle 
    err = Module32First_(handle, Entry) 
    If err 
       Result = PeekS(@Entry\szExePath) 
    EndIf 
    CloseHandle_(handle) 
  EndIf  
  
  ProcedureReturn Result 
EndProcedure 

st = ElapsedMilliseconds()
For i = 1 To 1000
	path.s = GetEXEFromHandle()
Next
sp = ElapsedMilliseconds() - st
MessageRequester(path, Str(sp))
Bei mir braucht deine Methode bei 1000 Durchläufen 560 ms, die von mir gepostete nur 80 ms (ohne Debugger).
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Dann Deins noch schneller, schöner und mit Unicode-Support :mrgreen:

Code: Alles auswählen

Import "psapi.lib"
  EnumProcessModules(a.l,b.l,c.l,d.l) As "_EnumProcessModules@16"
  CompilerIf #PB_Compiler_Unicode
  GetModuleFileNameEx(a.l,b.l,c.l,d.l) As "_GetModuleFileNameExW@16"
  CompilerElse
  GetModuleFileNameEx(a.l,b.l,c.l,d.l) As "_GetModuleFileNameExA@16"
  CompilerEndIf
EndImport

Procedure.s GetEXEFromHandle(nHWnd.l = 0)
 
  Protected nProcID, nResult, nTemp, hProcess
  Protected sFile.s
  Dim lModules.l(200)
 
  If nHwnd = 0
     nHWnd = GetForegroundWindow_()
  EndIf
 
  ; ProcessID ermitteln
  If GetWindowThreadProcessId_(nHWnd, @nProcID) <> 0
    ; Prozess-Handle ermitteln
    hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, 0, nProcID)
    If hProcess <> 0
      ; Module des Prozess enumerieren
      nResult = EnumProcessModules(hProcess, @lModules(0), 200, @nTemp)
      If nResult <> 0
        ; Dateiname ermitteln
        sFile = Space(260)
        nResult = GetModuleFileNameEx(hProcess, 0, @sFile, Len(sFile))
        sFile = LCase(Left(sFile, nResult))
       
      EndIf
     
      ; Handle schließen
      CloseHandle_(hProcess)
    EndIf
  EndIf
  ProcedureReturn sFile
EndProcedure
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Ich hole das aber mal wieder hoch, da ich auf http://www.vbarchiv.net/archiv/tipp_det ... p?pid=1018 eine Möglichkeit gefunden habe, Den Filenamen, der zu einen Fenster gehört zuverlässiger zu ermitteln
Zuverlässiger?
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

@ts - soft,
Nagut, ich gebs zu, das ist jetzt schöner, schneller und mit Unicode - Unterstützung, dem habe ich nichts mehr entgegenzusetzen. :)

@Fluid Byte,
Ja, zuverlässiger, probiere das mal bei mehreren Fenstern.
1. Mit GetWindowModuleFilename:

Code: Alles auswählen

Procedure tp(hwnd, message, id, time)
	Protected fn.s{260}
	fhwnd = GetForegroundWindow_()
	SendMessage_(fhwnd, #WM_GETTEXT, 260, @wt.s)
	If GetWindowModuleFileName_(fhwnd, @fn, 260)
		SetGadgetText(0, wt + " - " +fn)
	Else
		SetGadgetText(0, wt + " - " + "Fehlgeschlagen")
	EndIf
EndProcedure

hwnd = OpenWindow(0, 0, 0, 600, 100, "WindowModuleFilename")
CreateGadgetList(hwnd)
StringGadget(0, 10, 40, 580, 20, "", #PB_String_ReadOnly)

StickyWindow(0, #True)

SetTimer_(hwnd, 0, 100, @tp())

Repeat

Until WaitWindowEvent() = #PB_Event_CloseWindow

Und Mit Openprocess ...

Code: Alles auswählen

Import "psapi.lib" 
  EnumProcessModules(a.l,b.l,c.l,d.l) As "_EnumProcessModules@16" 
  CompilerIf #PB_Compiler_Unicode 
  GetModuleFileNameEx(hProcess.l, hModule.l, *lpFilename, nSize) As "_GetModuleFileNameExW@16" 
  CompilerElse 
  GetModuleFileNameEx(hProcess.l, hModule.l, *lpFilename, nSize) As "_GetModuleFileNameExA@16" 
  CompilerEndIf 
EndImport 

Procedure.s GetEXEFromHandle(nHWnd.l = 0) 
  
  Protected nProcID, nResult, nTemp, hProcess 
  Protected sFile.s 
  Dim lModules.l(200) 
  
  If nHwnd = 0 
     nHWnd = GetForegroundWindow_() 
  EndIf 
  
  ; ProcessID ermitteln 
  If GetWindowThreadProcessId_(nHWnd, @nProcID) <> 0 
    ; Prozess-Handle ermitteln 
    hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, 0, nProcID) 
    If hProcess <> 0 
      ; Module des Prozess enumerieren 
      nResult = EnumProcessModules(hProcess, @lModules(0), 200, @nTemp) 
      If nResult <> 0 
        ; Dateiname ermitteln 
        sFile = Space(260) 
        nResult = GetModuleFileNameEx(hProcess, 0, @sFile, Len(sFile)) 
        sFile = LCase(Left(sFile, nResult)) 
        
      EndIf 
      
      ; Handle schließen 
      CloseHandle_(hProcess) 
    EndIf 
  EndIf 
  ProcedureReturn sFile 
EndProcedure

Procedure tp(hwnd, message, id, time)
	Protected fn.s{260}
	fhwnd = GetForegroundWindow_()
	SendMessage_(fhwnd, #WM_GETTEXT, 260, @wt.s)
	fn = GetEXEFromHandle(fhwnd)
	If fn <> ""
		SetGadgetText(0, wt + " - " +fn)
	Else
		SetGadgetText(0, wt + " - " + "Fehlgeschlagen")
	EndIf
EndProcedure

hwnd = OpenWindow(0, 0, 0, 600, 100, "OpenProcess")
CreateGadgetList(hwnd)
StringGadget(0, 10, 40, 580, 20, "", #PB_String_ReadOnly)

StickyWindow(0, #True)

SetTimer_(hwnd, 0, 100, @tp())

Repeat

Until WaitWindowEvent() = #PB_Event_CloseWindow


Wie du sehen wirst wird bei 1. Methode Fehlgeschlagen angezeigt wo die 2. Methode funktioniert.
Antworten