Seite 1 von 2

ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 13.10.2009 18:28
von al90
Hi All,

Da ich Gestern selbst mächtig probleme damit hatte, eine Routine zu finden die mir den hWnd-Handle
nach dem Ausführen einer Datei zurückliefert und ich dieses Problem aber inzwichen Lösen konnte,
möchte ich die Routine mal hier bekannt geben, damit sich andere nicht auch noch damit rumplagen müssen. :wink:

Also der Code ist recht Simpel. Er Startet eine Datei (mit Win+GUI) und liefert dabei statt der ProcessID den Fenster-Handle. (hWnd)
Ich denke mal der eine oder andere wird es sicherlich noch gebrauchen können. :allright:

Code: Alles auswählen

Procedure.i EnumWindowsCallBack(hwnd.i, Handle.i)

  Protected Title$ = Space(1024), ProcessID.i, st.i = #True

  GetWindowText_(hwnd, @Title$, Len(Title$))
  GetWindowThreadProcessId_(hwnd, @ProcessID)

  If Title$<>"" And IsWindowVisible_(hwnd)
    If ProcessID = PeekI(Handle)
      PokeI(Handle, hwnd)
      st = #False
    EndIf
  EndIf

  ProcedureReturn st

EndProcedure

Procedure.i Execute_WindowFile(Filename$, Parameter$, WorkDir$)

  Protected st.i, Handle.i, Check.i

  If FileSize(Filename$) > 0
    st = RunProgram(Filename$, Parameter$, WorkDir$, #PB_Program_Open)
  Else
    ProcedureReturn #Null
  EndIf

  Handle = ProgramID(st) : Check = Handle

  Repeat
    Delay(10)
    EnumWindows_(@EnumWindowsCallBack(), @Handle)
  Until Handle <> Check And IsWindow_(Handle) <> #Null

  CloseProgram(st)
  ProcedureReturn Handle

EndProcedure


file$ = GetEnvironmentVariable("SystemRoot") + "\System32\calc.exe"
hwnd = Execute_WindowFile(file$, "", "")
Delay(500)
CloseWindow_(hwnd)
Delay(500)
OpenIcon_(hwnd)
Delay(1500)
SendMessage_(hwnd, #WM_CLOSE, 0, 0)
Debug "Window-Handle ( hWnd.l ) = " + Str(hwnd)
Getestet unter Vista & 7

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 13.10.2009 21:01
von milan1612
Sehr brauchbarer Code, danke schön :allright:
Funzt übrigens auch unter Win 7...

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 13.10.2009 21:20
von edel
milan1612 hat geschrieben:Funzt übrigens auch unter Win 7...
Fragt sich nur wie lange.

Der Callback ist falsch, siehe hier : http://msdn.microsoft.com/en-us/library/ms633498.aspx

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 13.10.2009 21:27
von Thorium
Du solltest auch Integer verwenden anstatt Long. Unter x64 sind alle ID's und Handle Quads. So ist der Code nicht sicher lauffähig unter x64.

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 13.10.2009 22:04
von edel
Der Code ist auch sonst etwas komisch, z.b. :

- "While WindowHandle = #Null", startest du ein Programm das versteckt oder gar kein Fenster hat, laeuft es sich tot.
- "IsWindowVisible_(hwnd) And Title$<>""" ist eher suboptimal, es gibt auch Fenster da steht nüscht drin und sichtbar muss sich auch nicht sein. In diesem Fall laeuft sich das Programm wieder einen Wolf.
- Wenn das Fenster gefunden wurde, waere ein vorzeitiger Abbruch auch nicht verkehrt.
- die Globalen Variablen wuerde ich entfernen und lieber eine Variable mit Struktur nehmen, diese wird dann bei EnumWindows als Parameter uebergeben, so kann man das auch in einem anderen Thread laufen lassen.

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 13.10.2009 22:24
von al90
milan1612 hat geschrieben:Funzt übrigens auch unter Win 7...
Schön zu wissen. :D

@Thorium & @edel

Ja ich weis das der code noch ausbaufähig ist und einiges geändert werden muss/sollte.
Hab ihn mal auf die schnelle zusammengeschustert, mit Teilweise schnippseln hier vom Board.
Werde es mal noch abändern. Ansonsten steht es ja jedem frei den Code selbst nach seinem
Geschmack anzupassen. :wink:

Was die Fenster betrifft; Das war auch so beabsichtigt. Es sollen damit in erster Linie Windowed-
Fenster-Apps geladen werden. Deshalb auch die Bezeichnung Execute_WindowFile() für die proc. :wink:

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 13.10.2009 22:39
von Thorium
al90 hat geschrieben: @Thorium & @edel

Ja ich weis das der code noch ausbaufähig ist und einiges geändert werden muss/sollte.
Hab ihn mal auf die schnelle zusammengeschustert, mit Teilweise schnippseln hier vom Board.
Werde es mal noch abändern. Ansonsten steht es ja jedem frei den Code selbst nach seinem
Geschmack anzupassen. :wink:
War auch nur als konstruktive Kritik gemeint. Generell lohnt es sich sich anzugewöhnen Integer statt Long und Quad zu verwenden. Erspart einem die Umstellung und damit verbundene Fehlersuche, wenn man mal auf x64 umsteigt, was früher oder später sowieso zum muss wird. ;)

Long und Quad machen nurnoch Sinn wenn diese Datentypen explicit erforderlich sind. Z.B. bei Dateiheadern und anderen Strukturen oder Quad auch wenn man mit großen Zahlen hantieren muss. Für alles andere Integer.

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 14.10.2009 00:41
von al90
Thorium hat geschrieben:War auch nur als konstruktive Kritik gemeint.
Kein problem. Kritik gehört eben mal dazu. Egal ob gut oder schlecht :wink:

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 14.10.2009 23:50
von al90
So hab den Code jetzt nochmal ein wenig überarbeitet. :wink:

Folgende Änderungen:

1) Fehler in der CallbackProc behoben.
2) Die ProgramID von RunProgram() wird jetzt direkt an der CallbackProc übergeben.
3) Die CallbackProc wird nun vorzeitig verlassen, sobald der Handle ermittelt wurde.
4) Wenn die Datei nicht gefunden wurde, wird jetzt '0' zurückgegeben, statt in einer EndlosSchleife hängen zu bleiben.

Code: Alles auswählen

Procedure.l EnumWindowsCallBack(hwnd, ProgramID.l)

  Protected Title$ = Space(1024), ProcessID.l, st.l = #True
  Shared WindowHandle.l

  GetWindowText_(hwnd, @Title$, Len(Title$))
  GetWindowThreadProcessId_(hwnd, @ProcessID)

  If IsWindowVisible_(hwnd) And Title$<>""
    If ProcessID = ProgramID
      WindowHandle = hwnd
      st = #False
    EndIf
  EndIf

  ProcedureReturn st

EndProcedure

Procedure.l Execute_WindowFile(Filename$, Parameter$, WorkDir$)

  Protected st
  Shared WindowHandle.l

  If FileSize(Filename$) > 0
    st = RunProgram(Filename$, Parameter$, WorkDir$, #PB_Program_Open)
  Else
    ProcedureReturn 0
  EndIf

  While WindowHandle = #Null
    Delay(10)
    EnumWindows_(@EnumWindowsCallBack(), ProgramID(st))
  Wend

  CloseProgram(st)
  ProcedureReturn WindowHandle

EndProcedure


file$ = GetEnvironmentVariable("SystemRoot") + "\System32\calc.exe"
hwnd = Execute_WindowFile(file$, "", "")
Delay(500)
CloseWindow_(hwnd)
Delay(500)
OpenIcon_(hwnd)
Debug "Window-Handle ( hWnd.l ) = " + Str(hwnd)
BTW: Integer habe ich erstmal weggelassen, da ich eh kein 64bit System zum Testen habe.

Re: ExecuteFile mit hWnd Rückgabewert (Fenster-Handle)

Verfasst: 14.10.2009 23:59
von ts-soft
al90 hat geschrieben: BTW: Integer habe ich erstmal weggelassen, da ich eh kein 64bit System zum Testen habe.
Was willste da Testen? Defaultvariable ist nicht mehr long sondern integer, immer.
Du brauchst da nichts testen und ich brauch mir nichts anpassen :)

Gruß
Thomas