Entwickler-Ecke
Windows API - Caller einer DLL ermitteln
DerNetteNachbar - Do 18.12.08 13:27
Titel: Caller einer DLL ermitteln
Hallo erstmal, ich würde ganz gerne in einer DLL den Aufrufer bestimmen, sprich die Anwendung die meine DLL aufgerufen hat. Gibt es dafür bereits eine API Funktion oder muss man sich da was basteln?
MfG
Nachbar
DerNetteNachbar - Do 18.12.08 14:11
Ich würde aber ganz gerne das Handle der Anwendung bekommen, bzw. das Handle vom TOP Fenster der Anwendung
jaenicke - Do 18.12.08 14:27
Dann ist vermutlich das hier das richtige, GetCurrentProcessId:
http://msdn.microsoft.com/en-us/library/ms683180(VS.85).aspx
Für welches Programm soll die DLL denn sein? Ich meine, normalerweise werden doch alle nötigen Informationen direkt an ein Plugin übergeben (wenn es ein Plugin für ein anderes Programm ist). Da scheint die Schnittstelle zwischen Anwendung und DLL nicht so ganz passend zu sein, aber wenn das nicht dein eigenes Programm ist, für das die DLL ist, dann kannst du da natürlich nichts dran ändern.
DerNetteNachbar - Do 18.12.08 15:19
Und wie komme ich von der ProzessID jetzet auf das Handle des TOP Fensters.
DerNetteNachbar - Do 18.12.08 15:25
Ich dachte da gibt es eine globale Funktion dafür. Das was in den Thread besprochen wird ist doch Quark.
jaenicke - Do 18.12.08 15:36
Wenn es dein eigenes Programm ist, ist die saubere Lösung ja auch über eine exportierte Prozedur die DLL zu initialisieren. Dann kannst du aus der Anwendung alle nötigen Daten übergeben und du sparst dir diese ganzen Verrenkungen. :nixweiss:
Wenn es nicht dein eigenes Programm ist, dann musst du dich eben verrenken.
Delete - Do 18.12.08 15:40
Das sag ich doch die ganze Zeit.
jaenicke - Do 18.12.08 15:51
Stimmt, ich sehs schon, im anderen Thread. Naja, wenns ihm Spaß macht sich das Leben schwer zu machen... :nixweiss:
DerNetteNachbar - Do 18.12.08 16:25
Hey Leute dank euch für euere Vorschläge es mir leichter zumachen. Da ich aber fest entschlossen bin es auf die Art(API Funktionen) zu machen um mich auch in die API Welt einzuarbeiten werde ich diesen Konzept weiterhin durchziehen.
Ich hoffe mir oder irgenteinem von euch kommt ein Geistesblitz^.
MfG
Delete - Do 18.12.08 16:28
Z.B. mit GetWindowThreadProcessId, aber das hatten wir doch neulich erst.
jaenicke - Do 18.12.08 16:33
DeddyH hat folgendes geschrieben : |
Z.B. mit GetWindowThreadProcessId, aber das hatten wir doch neulich erst. |
Das wäre ja genau die umgekehrte Richtung, er braucht ja das Fenster. Und ich kenne keine direkte Möglichkeit es zu bekommen. Wie es geht steht ja in dem verlinkten Thread. Ich glaube nicht, dass es einfacher geht. :nixweiss:
Wie sollte es auch einfacher gehen, bei einem Delphi-Programm hat man das versteckte Application-Fenster, bei anderen Programmen nicht, usw., deshalb sehe ich keine andere Möglichkeit als alle Fenster des Prozesses durchzugehen und anzuschauen.
Delete - Do 18.12.08 16:45
Genau so habe ich das im anderen Thread ja auch gemacht. Ein "Durchgehen" wird sich nicht umgehen lassen, ob man das von dieser oder von der anderen Seite angeht (3 * "gehen" in einem Satz *gg*).
jaenicke - Do 18.12.08 17:07
DerNetteNachbar hat folgendes geschrieben : |
Ich dachte da gibt es eine globale Funktion dafür. |
Und um dazu noch etwas zu sagen:
Warum sollte es etwas dafür geben? Du willst es auf diese Weise machen, das ist aber nicht die normale Vorgehensweise. Wenn du das so machen willst, ist das ja deine Sache, aber warum sollte es dafür etwas fertiges geben?
Das ist wie wenn du den Trampelpfad nimmst statt eines befestigten Wegs und dich dann ärgerst, wenn es keine Brücke über einen Bach gibt. ;-)
DerNetteNachbar - Do 18.12.08 17:15
Alles klar Leute, ich habs gemerkt das es zu nichts führt. Nur das Problem immernoch ich bekomme doe falsche Process ID aus der DLL. Nämlich ihre eigene und nicht die der aufrufenden Application. Versucht hab ich es mit :
Delphi-Quelltext
1: 2:
| GetWindowThreadProcessID GetCurrentProcessID |
MfG
Delete - Do 18.12.08 17:20
Richtig, die DLL hat ihr eigenes Prozesshandle. Du könntest nun über Umwege versuchen, über FindWindow und GetWindowThreadProcessId das Prozesshandle Deiner Anwendung herauszufinden, bei evtl. mehreren Instanzen oder Fenstern mit gleichem Titel und gleichem Classname kann das aber arg danebengehen. U.a. aus diesen Gründen wollen wir Dir ja nahelegen, das auf anderem Wege zu machen.
jaenicke - Do 18.12.08 17:22
Es geht, ich hatte die Doku falsch verstanden was GetCurrentProcessID anging :oops:. Richtig sollte es mit
Delphi-Quelltext
1:
| MyHandle := GetModuleHandle(nil); |
gehen, wenn ich das richtig verstehe:
DerNetteNachbar - Do 18.12.08 17:28
Daraufhin wird mir irgentein komisches Handle gesenden was ich gar nicht mit WinSpy ansehen kann. Komisch
Delete - Do 18.12.08 17:30
Das ist ja auch ein Prozess- und kein Fensterhandle.
DerNetteNachbar - Do 18.12.08 17:34
Joa und nu...den ProzessHandle konnte ich auch damit ermitteln
Delphi-Quelltext
1: 2:
| processHandle := OpenProcess(PROCESS_TERMINATE or PROCESS_QUERY_INFORMATION, False, hprocessID); |
Ich brauche ja immernoch das TOP Fenster.
Delete - Do 18.12.08 17:40
Was soll das TOP-Fenster sein?
DerNetteNachbar - Do 18.12.08 17:43
Das erste Fenster was in der Anwendung aufgerufen wird auch das TOP Level genannt.
Delete - Do 18.12.08 17:46
Und wodurch zeichnet sich das aus? Ein Flag TOP_WINDOW oder so wäre mir neu.
DerNetteNachbar - Do 18.12.08 17:50
Deshalb auch meine Frage ob es nicht eine Kennzeichnung gibt woran man es festmachen könnte.
Delete - Do 18.12.08 17:52
Zumindest mir ist keine bekannt.
DerNetteNachbar - Do 18.12.08 18:05
Schade, ich wüsste jetzt nicht wie ich das jetzet realisieren könnte.
DerNetteNachbar - Fr 19.12.08 10:37
PUSH
Delete - Fr 19.12.08 10:58
Wo liegt denn jetzt noch Dein Problem?
jaenicke - Fr 19.12.08 11:06
Das sind aber kurze 24 Stunden, pushen ist erst dann erlaubt. :roll:
Es gibt nun einmal kaum eine andere gute Möglichkeit als alle Prozesse durchzugehen...
Den Link hast du gesehen...
Du kannst es mit Win32_Process via WMI versuchen, da gibt es ParentProcessId, ich vermute damit macht es auch der ProcessExplorer:
http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx
Aber ob das eine so gute Lösung für diesen Zweck ist bin ich mir nicht so sicher. Da bekommst du jedenfalls, wenn das klappt, die ProcessId, und kannst dann die Fenster des Prozesses durchgehen.
Hast du eins gefunden kannst du
GetAncestor [
http://msdn.microsoft.com/en-us/library/ms633502(VS.85).aspx] mit GA_ROOT versuchen um das oberste Parent Window zu finden.
Die schlechteste Lösung wäre, deine Botschaft an alle Fenster, die du mit EnumWindows bekommst zu schicken. Darunter wird auch das deiner Anwendung sein.
Naja, aber da du deine Software ja wohl kaum weitergeben willst (dann würdest du es ja hoffentlich sauber programmieren), kannst du ja auch das machen... Solange du das nicht bei Software machst, die du veröffentlichen willst.
DerNetteNachbar hat folgendes geschrieben : |
Schade, ich wüsste jetzt nicht wie ich das jetzet realisieren könnte. |
Normal :nixweiss:
DerNetteNachbar - Fr 19.12.08 11:06
Naja das Problem ist immer noch das ich die falsche ProzessID bekomme wenn ich in meiner DLL
Delphi-Quelltext
1: 2:
| GetCurrentProcess() oder GetWindowThreadProcessID |
aufrufe, nämlich die der DLL. Ich möchte aber die ProzessID vom Elternprozess in dem Fall der aufrufende EXE Datei erhalten umso dann auf das MainWindow zu kommen.
Delete - Fr 19.12.08 11:12
GetModuleHandle(nil) sollte laut MSDN das Richtige sein, hat jaenicke doch bereits gepostet.
jaenicke - Fr 19.12.08 11:16
DerNetteNachbar hat folgendes geschrieben : |
Da ich aber fest entschlossen bin es auf die Art(API Funktionen) zu machen um mich auch in die API Welt einzuarbeiten |
Die einzige sinnvolle Möglichkeit dafür ist selbst in der API Referenz zu suchen, nur dadurch lernst du diese kennen. Und genau das ist das wichtige. Ich kenne nicht alle Funktionen auswendig, ich weiß aber wie ich in der Referenz etwas finde.
Und das lernst du nicht, wenn du um Funktionen zu finden jedesmal nachfragst. :nixweiss:
DerNetteNachbar - Fr 19.12.08 11:25
GetModuleHandle(nil) klappt nicht wirklich, denn es liefert mir ein unbekanntes Handle, das habe ich aber auch schon mal gepostet.
jaenicke - Fr 19.12.08 11:39
DerNetteNachbar hat folgendes geschrieben : |
GetModuleHandle(nil) klappt nicht wirklich, denn es liefert mir ein unbekanntes Handle, das habe ich aber auch schon mal gepostet. |
Das kann ich nicht reproduzieren. Ich habe es gerade getestet, bei mir ist das Handle gültig. :nixweiss:
Zum Test habe ich GetModuleFileName darauf angewendet, es liefert mir Pfad und Dateiname der Exe, nicht der DLL, also wie es sein soll. Es ist also ein gültiger HInstance Wert. Wie es in der Doku auch steht.
DerNetteNachbar - Fr 19.12.08 11:56
Das ist korrekt ich kriege den Pfad zu den EXE Dateien, allerdings liefert mir diese Funktion zweimal den gleichen Handle Wert. Sprich ich rufe die DLL aus zwei verschiedenen EXE Dateien auf und mir wird immer ein und dasselbe Handle zurückgeliefert. Komischer Verlauf. Ich will aber genau diesen Wert eindeutig haben um diesen im nachhinein zu vergleichen und die Anwendung zu identifizieren.
jaenicke - Fr 19.12.08 12:04
Also ich habe gerade einen kleinen Test gemacht:
DLL
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function EnumWindowsProc(Hnd: HWND; lParam: LPARAM): Boolean; stdcall; begin Result := GetWindowLong(Hnd, GWL_HINSTANCE) <> GetModuleHandle(nil); if not Result then SendMessage(GetAncestor(Hnd, GA_ROOT), WM_USER + 100, 0, 1);
Result := True; end;
begin EnumWindows(@EnumWindowsProc, 0); end; |
Programm
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm99.Button1Click(Sender: TObject); begin FreeLibrary(LoadLibrary('Project100.dll')); end;
procedure TForm99.WndProc(var Msg: TMessage); begin if Msg.Msg = WM_TEST then ShowMessage(IntToStr(Msg.LParam)) else inherited; end; |
Jetzt habe ich das Programm mehrfach gestartet, und die MessageBox kam immer genau in dem Programm, das die DLL aufgerufen hat, genau wie es sein soll... :nixweiss:
Und durch die Zeile
Result := True; werden ja explizit alle Fenster durchgegangen.
Motzi - Sa 20.12.08 17:03
Also hier werden alle möglichen Dinge vermischt..!
Prozess-Handle != Prozess-ID != Fenster-Handle != Module-Handle
- Die Prozess-Id ist eine eindeutige Nummer die von Windows an die einzelnen Prozesse vergeben wird - diese erscheint auch im Taskmanager (PID).
- Ein Prozess-Handle erhält man über OpenProcess. Es handelt sich hierbei um einen Index einer internen Tabelle mit allen Kernel-Objekten des Prozesses. Ein solches Handle ist also immer nur innerhalb des eigenen Prozesses gültig!
- Ein Fenster-Handle ist eine von Windows vergebene eindeutige Nummer für ein Fenster.
- Ein Module-Handle ist eigentlich nichts anderes als die Basisadresse des Moduls im entsprechenden Prozessraum.
jaenicke - Sa 20.12.08 17:41
Deshalb sollten ja diese beiden Handles innerhalb des Programms gültig sein, die hInstance des Prozesses sollte dann dem (ebenfalls internen) Modulhandle entsprechen.
jaenicke hat folgendes geschrieben : |
DLL 1: 2: 3:
| function EnumWindowsProc(Hnd: HWND; lParam: LPARAM): Boolean; stdcall; begin Result := GetWindowLong(Hnd, GWL_HINSTANCE) <> GetModuleHandle(nil); | |
Ob das jetzt nur zufällig funktioniert weiß ich nicht, aber die verlinkte Lösung oder eine ganz saubere Lösung stießen ja auf kein Interesse beim Threadersteller. :nixweiss:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!