handle auf Fenster bekommen
-
Ersteinmal Danke net.
Habe mal bei msdn geguckt und zu 'ZwQueryInformationProcess' oder 'NtQueryInformationProcess' sagen die dort:
[NtQueryInformationProcess may be altered or unavailable in future versions of Windows. Applications should use the alternate functions listed in this topic.]
Habe aber im Internet einige Beispiel gefunden, aber diese benötigen immer die '<vdmdbg.h>' Datei.
Diese besitzt aber meine DEV C++ SDK nicht.Bei "toolhelp32" habe ich das Problem das ich nicht weis wie ich nun an meine gewünschte Information kommen soll.
Ich kann zwar den Pfad der gestarteten Anwendungen auslesen un den Modulnamen aber das nützt mir auch nix.
Da der Anwender ja mehr als einmal das gleiche Programm starten kann und ich somit auch nicht herausfinden kann welches nun mein "Erzeuger" war.Da muss es doch eine einfache Lösung zu geben... hat nicht noch jemand einen Tipp parat?
mfg rendner
-
Alle Fenster durchgehen und mit
GetWindowThreadProcessId
festellen ob es vom gesuchten Prozess stammt.Dir ist aber schon bewusst dass ein Prozess mehrere Fenster haben kann?
Vieleicht möchtest du dem startendenden Program ja nur etwas mitteilen, dann wär
PostThreadMessage evtl. 'ne Überlegung.
-
Habs glaub ich so halbwegs mit "toolhelp32" hinbekommen, muss das nur noch in Code umsetzen.
Theorie:
Ich lese einfach von meinem "Fenster" (Prozess) die ParentProcessID aus mittels "th32ParentProcessID".
Somit komme ich an die ID des "erzeugers" meines Fensters und kann mir ein handle auf diesen besorgen. (oder sehe ich das falsch...?)Dir ist aber schon bewusst dass ein Prozess mehrere Fenster haben kann?
Würde das mit den mehreren Fenstern meine Idee zu nichte machen?
Vieleicht möchtest du dem startendenden Program ja nur etwas mitteilen, dann wär
PostThreadMessage evtl. 'ne Überlegung.Dem zu startendem Programm kann ich leider nichts direkt mitteilen, aber ich will das Fenster was mich erzeugt hat, "manipulieren".
Und deshalb brauche ich das handle auf das "erzeuger" Fenster.Ich hoffe man versteht was ich meine, da ich mit den Begriffen nicht so fit bin und eventuell was verwechselt habe.
mfg rendner
-
Ich geh als Beispiel davon aus dein Programm wird von Winamp gestartet und du möchtest Winamp minimieren.
Die ProzessId hast du.
Mit EnumWindows gehst du alle Toplevel Fenster durch.
Testest jeweils ob das Fenster zum Prozess gehört.
Nur welches von den 3 Fenstern nimmst du?
Wenn das Programm nur ein Hauptfenster hat sollte die Erfolgswahrscheinlichkeit aber hoch sein.
(theoretisch könnte das Hauptfenster auch noch von einem eigenen Thread erstellt worden sein, ist aber nicht gängige Praxis)
-
Ich glaube in meinem Fall gehts...
Kann mir vielleicht einer helfen?
Ich übergebe der Funktion "GetWindowThreadProcessId" ein handle auf mein Fenster und lasse mir meine ProcessId mitteilen.
Aber eigentlich will ich ja gleich die ParentProcessId haben, wie muss ich das anstellen?DWORD dwProcessID; char c[10]; GetWindowThreadProcessId( hwnd, &dwProcessID); sprintf( c, " 0x%08X", dwProcessID); MessageBox( NULL, c, "myProcessId", MB_OK);mfg rendner
-
Wenn Du die Parent-ProzessId haben willst, dann musst Du auch ein Fenster-Handle Deines Parents übergeben...
Aber ich dachte Du hast schon die Parent ProzessID!?
-
auch mit toolhelp?
HANDLE hSnap; hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); PROCESSENTRY32 pe32; pe32.dwSize = sizeof( PROCESSENTRY32 ); Process32First( hSnap, &pe32 ); while (pe32.th32ProcessID!= gesuchteProcessID) if(!Process32Next( hSnap, &pe32 )) break; parrentId=pe32.th32ParentProcessID;geht wahrscheinlich auch einfacher, finde ich aber auf die scnelle nicht
-
Dein Ansatz ist gar nicht so schlecht...
http://www.codeproject.com/threads/ParentPID.aspDu kannst auch "Win32_Process" aus dem WMI nehmen, das liefert es auch direkt...
-
Danke LUI, hatte mir das jetzt auch mit dem vergleichen ausgedacht.
Dachte aber vorher das ich das eventuell nicht machen muss wen ich schon meine eigene ID habe.Wenn Du die Parent-ProzessId haben willst, dann musst Du auch ein Fenster-Handle Deines Parents übergeben...
Aber ich dachte Du hast schon die Parent ProzessID!?Nein, ich habe quasi nur ein handle auf mein eigenes Fenster und hole mir über diese meine ID.
Die ID des "erzeugers" meines Fenster will ich ja haben (eigentlich ein handle auf dieses Fenster).Du kannst auch "Win32_Process" aus dem WMI nehmen, das liefert es auch direkt...Habe mir das unter msdn angeschaut und steige da leider gar nicht durch.
Könntest du das kurz erklären falls es für mich in Frage kommen würde, es würde ja zumindest der Vergleich mit allen Prozessen wegfallen wenn ich dies nutzen könnte.Am besten ich schildere noch einmal meine Thematik:
Meine Anwendung wird durch einen Aufruf eines anderen Fensters (auf das ich kein einfluß habe) gestartet.
Nun will ich auf dieses Fenster ein handle haben ( über dieses Fenster weis ich selber nichts, ausser das es meins erzeugt hat ).Schon einmal jetzt vielen Dank für eure bisherige Hilfe!
mfg rendner
-
rendner schrieb:
Nein, ich habe quasi nur ein handle auf mein eigenes Fenster und hole mir über diese meine ID.
Man kann es auch kompliziert machen... warum rufst Du nicht "GetCurrentProcessId" auf?
rendner schrieb:
Du kannst auch "Win32_Process" aus dem WMI nehmen, das liefert es auch direkt...Habe mir das unter msdn angeschaut und steige da leider gar nicht durch.
Könntest du das kurz erklären falls es für mich in Frage kommen würde, es würde ja zumindest der Vergleich mit allen Prozessen wegfallen wenn ich dies nutzen könnte.Ist leider in C++ etwas komplizierter... aber trotzdem:
#define _WIN32_DCOM #include <windows.h> #include <tchar.h> #include <Wbemidl.h> #pragma comment(lib, "Wbemuuid.lib") #include <comutil.h> #pragma comment(lib, "comsupp.lib") int _tmain() { CoInitialize(NULL); //Security needs to be initialized in XP first and this was the major problem //why it was not working in XP. if(CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0 ) != S_OK) return 1; IWbemLocator * pIWbemLocator = NULL; IWbemServices * pWbemServices = NULL; IEnumWbemClassObject * pEnumObject = NULL; BSTR bstrNamespace = (L"root\\cimv2"); if(CoCreateInstance ( CLSID_WbemAdministrativeLocator, NULL , CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER , IID_IUnknown , ( void ** ) & pIWbemLocator ) != S_OK) return 1; if(pIWbemLocator->ConnectServer( bstrNamespace, // Namespace NULL, // Userid NULL, // PW NULL, // Locale 0, // flags NULL, // Authority NULL, // Context &pWbemServices ) != S_OK) return 1; wchar_t szQueryStr[200]; swprintf(szQueryStr, L"Select * from Win32_Process WHERE ProcessId = %u", GetCurrentProcessId()); HRESULT hRes; BSTR strQuery = szQueryStr; BSTR strQL = (L"WQL"); hRes = pWbemServices->ExecQuery(strQL, strQuery,WBEM_FLAG_RETURN_IMMEDIATELY,NULL,&pEnumObject); if(hRes != S_OK) { //MessageBox("Could not execute Query"); return 1; } ULONG uCount = 1, uReturned; IWbemClassObject * pClassObject = NULL; hRes = pEnumObject->Reset(); if(hRes != S_OK) { //MessageBox("Could not Enumerate"); return 1; } hRes = pEnumObject->Next(WBEM_INFINITE,uCount, &pClassObject, &uReturned); if(hRes != S_OK) { //MessageBox("Could not Enumerate"); return 1; } VARIANT v; BSTR strClassProp = SysAllocString(L"ParentProcessId"); hRes = pClassObject->Get(strClassProp, 0, &v, 0, 0); if(hRes != S_OK) { //MessageBox("Could not Get Value"); return 1; } SysFreeString(strClassProp); if FAILED(VariantChangeType(&v, &v, 0, VT_UI4)) return 1; // ############################################################## // #### HERE YOU HAVE IT!!! ##################################### DWORD dwParentProcessId = V_UI4(&v); _bstr_t bstrPath = &v; //Just to convert VARIANT to BSTR wchar_t* strPath= bstrPath; if (SUCCEEDED(hRes)) MessageBoxW(NULL, strPath, L"Parent process ID", MB_OK); else { return 1; } VariantClear( &v ); pIWbemLocator->Release(); pWbemServices->Release(); pEnumObject->Release(); pClassObject->Release(); CoUninitialize(); }Das Problem mit dem Fenster hast Du dann immer noch... aber jetzt musst Du (wie schon mal von jemandem beschrieben) nur noch alle Top-Level Windows durchgehen und jede ProzessId eines Fenster-Handles mit dem hier ermittelten ParentId vergleichen. Und dann noch hoffen, dass der Parent nur ein Top-Level Fenster hat... sonst musst Du die kirterien noch etwas genauer wissen...
PS: Der obige Code ist nur etwas abgewandlet von
http://www.codeproject.com/system/Using_WMI_in_Visual_C__.asp
-
Uff, das ist zu "unleserlich" für mich, ich glaub da bleib ich beim toolhelp32.
Aber trotzdem Danke.Ich glaube es läuft so wie ich es wollte, muss ich jetzt in mein grösseres Vorhaben einbauen und hoffen das es dort dann auch noch funktioniert.
(werd mich die Tage mal ransetzen und meinen "QuellCode" aufräumen)Ein riesiges Danke an Euch, hätte noch nicht mal ansatzweise dies Bewerkstelligen können!
mfg rendner
-
Das klappt alles soweit wunderbar, jetzt müsste ich nur noch Wissen wie ich herausbekomme ob der user meine Applikation gestartet hatt (per Doppelklick) oder ein Programm.
Kann man dies auch gleich mit herausfinden, oder muss dies etwas anders geschehen?
mfg rendner
-
Ähem wieso sollte ein Program das ein anderes startet irgendwelche Informationen darüber erteilen wie es zu diesen 'entschluss' gekommen ist.
Wenn du abfragst ob explorer.ex oder iexplore.exe der Elternprozess ist solltest du aber davon ausgehen können dass eine Benutzerinteraktion(Maus/Tastatur) stattgefunden hat. Ausnahmen: Autostartordner, dubios BHOs und evtl. der Taskplaner(?)
-
Ähem wieso sollte ein Program das ein anderes startet irgendwelche Informationen darüber erteilen wie es zu diesen 'entschluss' gekommen ist.
Ich wollt ja keinen "Beweggrund" mitgeteilt bekommen, ich wollt nur wissen ob der user die Anwendung (durch doppelklick der exe) gestartet hatt.
Um zu erfahren ob es die explorer.exe oder iexplorer.exe war müsste ich ja mit "MODULEENTRY32" arbeiten, da "PROCESSENTRY32" und anschliesendes "GetWindowText" nicht die benötigte Auskunft erteilen.
Dachte es gäbe da ne einfache Funktion mit der man soetwas prüfen kann.
(naja auch nicht so schlimm, werds schon irgendwie hinbiegen)Nochmals Danke.
mfg rendner
-
naja. man kann sehr viel über einen prozess rauskriegen aber ob der aufgrund einer benutzeraktion gestartet wurde oder automatisch stelle ich mir sehr schwierig vor. auch wenn du weisst, dass der elternprozess unterm benutzeraccount läuft der gerade angemeldet ist, sagt das ja noch lange nicht, dass der user den manuell gestartet hat