AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Wie findet man Fenster, deren Namen man nicht genau kennt?
Thema durchsuchen
Ansicht
Themen-Optionen

Wie findet man Fenster, deren Namen man nicht genau kennt?

Ein Thema von Codehunter · begonnen am 14. Sep 2011 · letzter Beitrag vom 15. Sep 2011
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#1

Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 10:57
Hallo!

Ich möchte ein Programm schreiben, das für das Update einer Anwendung zuständig ist. Das Update-Tool muss natürlich nachschauen, ob noch irgendwelche Instanzen der zu updatenden Anwendung laufen und eine Liste dieser Instanzen anzeigen. Eben so wie man das von Firefox-Installationen etc. kennt die beim Update warten bis das letzte Browserfenster geschlossen ist.

Das Problem dabei: FindWindow findet ja nur Fenster, wenn man den exakten Title-String angibt. Der ändert sich aber, je nach dem welche Datei in der Anwendung gerade geöffnet ist. Der Classname ist auch nicht eindeutig, der verändert sich da beim Anwendungsstart eine GUID als Classname gesetzt wird.

Wie kann man eine Anwendung noch ausfindig machen?

Grüße
Cody
  Mit Zitat antworten Zitat
Benutzerbild von chaosben
chaosben

Registriert seit: 27. Apr 2005
Ort: Görlitz
1.358 Beiträge
 
Delphi XE2 Professional
 
#2

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 11:10
Ich würde über die Process-Liste und dann über den Pfad zur .exe gehen. Letzteren musst du ja sowieso kennen, um ein Update zu machen.
Benjamin Schwarze
If I have seen further it is by standing on the shoulders of Giants. (Isaac Newton)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.620 Beiträge
 
Delphi 12 Athens
 
#3

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 11:14
Könnte man nicht die Taskliste durchgehen (z.B. mit CreateToolhelp32Snapshot), nach dem entsprechenden Prozess suchen und bei Fund die ProcessID ermitteln? Anschließend dann mit EnumWindows alle Fenster durchlaufen und mit GetWindowThreadProcessID vergleichen. Allerdings bin ich mir gerade nicht sicher, ob die erforderlichen Angaben auch wirklich im TProcessEntry32-Record stehen, denke aber schon.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Singlepin

Registriert seit: 3. Sep 2011
10 Beiträge
 
#4

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 11:33
Meine Programme erstelle ich in der Regel so, daß sie nicht doppelt gestartet werden können.
Dazu erzeuge ich ein Memory-Mapped File in dem ich gleich noch das Handle der Application ablege.
Dein Setup-Programm braucht dann nur zu prüfen ob das Memory.Mapped File existiert
und könnte über das Handle die Anwendung z.b. automatisch schließen oder in den Fordergrund holen usw.
  Mit Zitat antworten Zitat
Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 12:16
Danke Jungs, manchmal reicht einem ein Stichwort damit man weiterkommt In dem Fall CreateToolhelp32Snapshot (übrigens wirklich kein treffender Name für diese Routine). Hier eine Delphi-Übersetzung des Sample-Codes der im PSDK hinterlegt ist:
Delphi-Quellcode:
uses
  tlhelp32;

procedure TForm1.Button1Click(Sender: TObject);
var
  hProcessSnap: THandle;
  hProcess: THandle;
  pe32: PROCESSENTRY32;
  dwPriorityClass: DWord;
begin
  Memo1.Lines.BeginUpdate;
  try
    hProcessSnap:= CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
    if hProcessSnap = INVALID_HANDLE_VALUE then begin
      Memo1.Lines.Add(#13#10#13#10'CreateToolhelp32Snapshot (of processes)');
      Exit;
    end;
    pe32.dwSize:= SizeOf(PROCESSENTRY32);

    if not Process32First(hProcessSnap, pe32) then begin
      Memo1.Lines.Add(#13#10#13#10'Error: Process32First');
      CloseHandle(hProcessSnap);
      Exit;
    end;

    repeat
      Memo1.Lines.Add(#13#10'=====================================================');
      Memo1.Lines.Add(Format('PROCESS NAME: %s', [pe32.szExeFile]));
      Memo1.Lines.Add('-----------------------------------------------------');

      dwPriorityClass:= 0;
      hProcess:= OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
      if hProcess = NULL then begin
        Memo1.Lines.Add(#13#10'Error: OpenProcess');
      end else begin
        dwPriorityClass:= GetPriorityClass(hProcess);
        if dwPriorityClass = 0 then begin
          Memo1.Lines.Add(#13#10'Error: GetPriorityClass');
          CloseHandle(hProcess);
        end;
      end;

      Memo1.Lines.Add(Format(' Process ID = 0x%08X', [pe32.th32ProcessID]));
      Memo1.Lines.Add(Format(' Thread count = %d', [pe32.cntThreads]));
      Memo1.Lines.Add(Format(' Parent process ID = 0x%08X', [pe32.th32ParentProcessID]));
      Memo1.Lines.Add(Format(' Priority base = %d', [pe32.pcPriClassBase]));
      Memo1.Lines.Add(Format(' Priority base = %d', [pe32.pcPriClassBase]));
      Memo1.Lines.Add(Format(' Executable = %s', [pe32.szExeFile]));

      if dwPriorityClass > 0 then begin
        Memo1.Lines.Add(Format(' Priority class = %d', [dwPriorityClass]));
      end;

    until not Process32Next(hProcessSnap, pe32);

    CloseHandle(hProcessSnap);
  finally
    Memo1.Lines.EndUpdate;
  end;
end;
Ist erstmal nur eine Dummy-Routine mit Ausgabe in ein Memo. Ich werde mir das jetzt so adaptieren dass ich über den Exe-Namen gehe, an die Process-ID eine Message schicke und mir von dort mit einer Message antworten lasse. So finde ich meine ganzen Ziel-Prozesse.
  Mit Zitat antworten Zitat
ASM

Registriert seit: 16. Aug 2004
165 Beiträge
 
Delphi 7 Enterprise
 
#6

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 12:27
Es geht auch so:

Code:
function FindWindowEx(partialTitle: string): HWND;
var
  hWndTemp: hWnd;
  iLenText: Integer;
  cTitletemp: array [0..254] of Char;
  sTitleTemp: string;
begin
  hWndTemp := FindWindow(nil, nil);
  while hWndTemp <> 0 do begin
    iLenText := GetWindowText(hWndTemp, cTitletemp, 255);
    sTitleTemp := cTitletemp;
    sTitleTemp := UpperCase(copy( sTitleTemp, 1, iLenText));
    partialTitle := UpperCase(partialTitle);
    if pos( partialTitle, sTitleTemp ) <> 0 then Break;
    hWndTemp := GetWindow(hWndTemp, GW_HWNDNEXT);
  end;
  result := hWndTemp;
end;
Beispiel:
Winword ist geöffnet mit irgendeinem Dokument. Das Fenster hat z.B. gerade den Titel "Dokument3 - Microsoft Word".
Das Word-Fenster trägt neben dem Titel des gerade geöffneten Dokuments immer auch den Textzusatz "Microsoft Word".

Du kannst also einfach mit
Code:
if FindWindowEx('Microsoft Word')<>0 then showmessage('Hi, Winword. Nice to meet you.')
else Showmessage('nix los hier');
feststellen, ob gerade irgendeine Instanz von Winword aktiv ist.

Entsprechend funktioniert das auch mit dem Adobe Reader, Mozilla Firefox, usw.
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#7

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 13:12
Dann doch lieber nach dem Dateinamen suchen. Ansonsten schließt man im schlimmsten Fall ein Fenster das einen ähnlichen Title hat.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
ASM

Registriert seit: 16. Aug 2004
165 Beiträge
 
Delphi 7 Enterprise
 
#8

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 14:16
Dann doch lieber nach dem Dateinamen suchen. Ansonsten schließt man im schlimmsten Fall ein Fenster das einen ähnlichen Title hat.

Die konkrete Frage war aber nun vielmehr folgende:
Zitat:
Das Update-Tool muss natürlich nachschauen, ob noch irgendwelche Instanzen der zu updatenden Anwendung laufen und eine Liste dieser Instanzen anzeigen.
Ich kann in dieser Frage von Codehunter keine Absicht erkennen, das Fenster per brute-force von außerhalb schließen zu wollen.
  Mit Zitat antworten Zitat
Delphi-Laie

Registriert seit: 25. Nov 2005
1.474 Beiträge
 
Delphi 10.1 Berlin Starter
 
#9

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 14:19
Könnte man nicht die Taskliste durchgehen (z.B. mit CreateToolhelp32Snapshot), nach dem entsprechenden Prozess suchen und bei Fund die ProcessID ermitteln? Anschließend dann mit EnumWindows alle Fenster durchlaufen und mit GetWindowThreadProcessID vergleichen. Allerdings bin ich mir gerade nicht sicher, ob die erforderlichen Angaben auch wirklich im TProcessEntry32-Record stehen, denke aber schon.
Ja, stehen sie (sofern ich Dich recht verstand), wobei man GetWindowThreadProcessID nach meiner Erinnerung allerdings extra aufrufen muß. In meinem Programm mit dem einfallslosen Namen "Prozesse" (auch hier im Forum zu finden) wird auch demonstriert, wie man die Fenster selektiv eines Prozesses finden bzw. sich auflisten lassen kann (ein einfacher Filter tut es, alternativ könnte man mit Enmthreadwindows alle Fenster aller Threads eines Prozesses erhalten). Ansonsten empfehle ich Luckies Programm "WinInfo", von dem ich einige Anregungen übernahm.

Geändert von Delphi-Laie (14. Sep 2011 um 15:21 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.048 Beiträge
 
Delphi 12 Athens
 
#10

AW: Wie findet man Fenster, deren Namen man nicht genau kennt?

  Alt 14. Sep 2011, 14:48
Wobei es auch sein kann, daß es andere Programme mit dem selben Fensternamen gibt,
oder das gefundene Fenster gehört zur gleichen EXE, aber in einem anderen Verzeichns.

Der einzige Weg, um ein bestimmtes Programm zu finden, geht also nur über den EXE Namen, inkl. Pfad.



Wenn man, bzw. das Setup, auf etwas zugreifen muß, welches gemeinsam genutzt wird (z.B. eine Datenbank),
dann muß man alle Instanzen finden, welche irgendwo laufen (unabhängig vom Pfad).

Für Letzteres könnte man bestimmt mit 'nem Mutex, oder mit anderen globalen möglichst eindeutigen Markern arbeiten.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:23 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz