Auf HWND von Prozess warten



  • lowbyte_ schrieb:

    In Zeile 35 hast Du kein return Wert. Hoffe aber dies ist ein schreib Fehler!?

    Vielleicht solltest Du mal einen Blick auf den Rückgabetyp der Funktion werfen.



  • Ultrablack schrieb:

    if(!CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) 
    	{
    		std_p(12, "Starting executable failed!\n");
    		return;
    	}
    
        WaitForInputIdle(pi.hProcess, INFINITE); // hilft hier laut MSDN!
    	c_pid = pi.hProcess; //c_pid ist für Übergabe der Prozess-Id für EnumWindows
    	EnumWindows(EnumWindowsProc, NULL);
    
    	CloseHandle(pi.hThread);
    	CloseHandle(pi.hProcess);
    }
    


  • hier ein Copy&Paste Code mit WaitForInputIdle UND WaitForSingleThread mit Ausgabe für die sichtbaren Fenster aus EnumWindows (jedoch scheint das Fenster des Prozesses trotzdem nicht auf!)

    #include "stdafx.h"
    #include "windows.h"
    #include <vector>
    using namespace std;
    vector<DWORD> c_pid;
    DWORD cc_pid;
    
    BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
    {
        char title[512];
        ZeroMemory(title, sizeof(title));
    
        GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));
    
    	if (!hWnd) return true;
    	if (!IsWindowVisible(hWnd)) return true;
    	if (!GetWindowTextLength(hWnd)) return true; 
    	if (strstr(title, "Program Manager") || strstr(title, "Start")) return true;
    
    	DWORD pid;
    	GetWindowThreadProcessId(hWnd, &pid);
    
    	if (pid==cc_pid) {} //do
    	cout << cc_pid << "-" << pid << "\n";
    
    	return true;
    }
    
    long prc_c()
    {
    	STARTUPINFO si;
    	PROCESS_INFORMATION pi;
    
    	ZeroMemory(&si, sizeof(si));
    	ZeroMemory(&pi, sizeof(pi));
    	si.cb = sizeof(si);
    
    	if(!CreateProcess("calc.exe", NULL, NULL, NULL, 
    		FALSE, 0, NULL, NULL, &si, &pi)) 
    	{
    		cout << "execute fail";
    		return 0;
    	}
    
            WaitForInputIdle(pi.hProcess, INFINITE);
    	c_pid.push_back(pi.dwProcessId);
    	CloseHandle(pi.hThread);
    	CloseHandle(pi.hProcess);
    	return 0;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int i;
    	HANDLE hThread1 = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)prc_c, 0, 0, 0);
    	WaitForSingleObject(hThread1, INFINITE);
    	CloseHandle(hThread1);
    
    	for (i=0; i<c_pid.size(); i++) {
    		cc_pid = c_pid[i];
    		EnumWindows(EnumWindowsProc, NULL);
    	}
    
    	system("PAUSE");
    	return 0;
    }
    

    @Belli: laut MSDN hilft es, hier jedoch nicht (s.o.)

    @HighLigerBiMBam: danke für den Hinweis, jedoch habe ich ebenfalls Threads benutzt und WaitForSingleObject hilft trotzdem nicht weiter (s.o.)



  • Belli schrieb:

    lowbyte_ schrieb:

    In Zeile 35 hast Du kein return Wert. Hoffe aber dies ist ein schreib Fehler!?

    Vielleicht solltest Du mal einen Blick auf den Rückgabetyp der Funktion werfen.

    Entschuldige hatte ich übersehen.



  • Ich habe Dein Beispiel mal auf das Allernötigste reduziert:

    #include "windows.h"
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
    {
        char title[512];
    
        GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));
    
        string str(title);
    
        if(str == "Rechner")
        	cout << "Rechner gefunden!" << endl;
    
        return true;
    }
    
    long prc_c()
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory(&si, sizeof(si));
        ZeroMemory(&pi, sizeof(pi));
        si.cb = sizeof(si);
    
        if(!CreateProcess("c:\\windows\\system32\\calc.exe", NULL, NULL, NULL,
            FALSE, 0, NULL, NULL, &si, &pi))
        {
            cout << "execute fail";
            return 0;
        }
    
        WaitForInputIdle(pi.hProcess, INFINITE);
        return 0;
    }
    
    int main()
    {
        prc_c();
    
        EnumWindows(EnumWindowsProc, NULL);
    
        return 0;
    }
    

    So wird "Rechner gefunden!" ausgegeben, wenn WaitForInputIdle auskommentiert wird, wird es nicht ausgegeben, WaitForInputIdle funktioniert also wie erwartet.



  • Belli schrieb:

    Ich habe Dein Beispiel mal auf das Allernötigste reduziert:

    #include "windows.h"
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
    {
        char title[512];
    
        GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));
        
        string str(title);
        
        if(str == "Rechner")
        	cout << "Rechner gefunden!" << endl;
    
        return true;
    }
    
    long prc_c()
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory(&si, sizeof(si));
        ZeroMemory(&pi, sizeof(pi));
        si.cb = sizeof(si);
    
        if(!CreateProcess("c:\\windows\\system32\\calc.exe", NULL, NULL, NULL,
            FALSE, 0, NULL, NULL, &si, &pi))
        {
            cout << "execute fail";
            return 0;
        }
    
        WaitForInputIdle(pi.hProcess, INFINITE);
        return 0;
    }
    
    int main()
    {
        prc_c();
        
        EnumWindows(EnumWindowsProc, NULL);
    
        return 0;
    }
    

    So wird "Rechner gefunden!" ausgegeben, wenn WaitForInputIdle auskommentiert wird, wird es nicht ausgegeben, WaitForInputIdle funktioniert also wie erwartet.

    Sorry ich hab vergessen zu erwähnen, dass der Fenster-Titel vorher nicht bekannt ist, nur die exe 😞



  • mcoocr schrieb:

    Sorry ich hab vergessen zu erwähnen, dass der Fenster-Titel vorher nicht bekannt ist, nur die exe 😞

    Darum geht es hier nicht. Ich zeige nur auf (und zwar mit dem Programm calc.exe als Beispiel, weil es in Deinem Beispiel auch genutzt wurde), dass WaitForInputIdle funktioniert.



  • Belli schrieb:

    Darum geht es hier nicht. Ich zeige nur auf (und zwar mit dem Programm calc.exe als Beispiel, weil es in Deinem Beispiel auch genutzt wurde), dass WaitForInputIdle funktioniert.

    Die Ausgabe funktioniert, jedoch ist das Fenster zu diesem Zeitpunkt nicht sichtbar bzw. nicht fertig geladen (IsWindowVisible).. somit kann ich z.B. ShowWindow nicht anwenden 😕



  • Wenn Du mein obiges Beispiel kompilierst und startest, wird der Rechner gestartet und angezeigt. Wenn Du

    BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
    {
        char title[512];
    
        GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));
    
        string str(title);
    
        if(str == "Rechner")
        {
        	cout << "Rechner gefunden!" << endl;
        	if(IsWindowVisible(hWnd))
        		cout << "Fenster ist sichtbar!";
        }
    
        return true;
    }
    

    codierst, wird auch der zweite Text ausgegeben. Ich fürchte, ich verstehe Dein Problem nicht. Nach wie vor geht es mir hier aber auch erst mal darum, dass WaitForInputIdle sehr wohl erst dann zurückkehrt, wenn der entsprechende Prozess fertig geladen und initialisiert ist - darum ging es ja auch primär in Deinem Eingangsposting.

    Der Punkt ist doch:
    WaitForInputIdle sorgt dafür, dass es in prc_c erst weitergeht, wenn die gestartete Anwendung initialisiert ist, und Du bekommst auch dass Handle des Hauptfensters in EnumWindowsProc angeliefert - darum ging es Dir doch ...



  • Belli schrieb:

    Wenn Du mein obiges Beispiel kompilierst und startest, wird der Rechner gestartet und angezeigt. Wenn Du

    BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
    {
        char title[512];
    
        GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));
        
        string str(title);
        
        if(str == "Rechner")
        {
        	cout << "Rechner gefunden!" << endl;
        	if(IsWindowVisible(hWnd))
        		cout << "Fenster ist sichtbar!";
        }
    
        return true;
    }
    

    codierst, wird auch der zweite Text ausgegeben. Ich fürchte, ich verstehe Dein Problem nicht. Nach wie vor geht es mir hier aber auch erst mal darum, dass WaitForInputIdle sehr wohl erst dann zurückkehrt, wenn der entsprechende Prozess fertig geladen und initialisiert ist - darum ging es ja auch primär in Deinem Eingangsposting.

    Der Punkt ist doch:
    WaitForInputIdle sorgt dafür, dass es in prc_c erst weitergeht, wenn die gestartete Anwendung initialisiert ist, und Du bekommst auch dass Handle des Hauptfensters in EnumWindowsProc angeliefert - darum ging es Dir doch ...

    Versuch mal

    cout << "Fenster ist sichtbar!";
    

    durch ShowWindow(hWnd, SW_HIDE) zu ersetzten, dir wird aufallen dass der Prozess auf diese Anweisung nicht reagiert und das Fenster "Rechner" normal anzeigen wird..

    Abgesehen davon wird bei mir nicht einmal "Fenster ist sichtbar!" ausgegeben (nur "Rechner gefunden!")



  • BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
    {
        char title[512];
    
        GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0]));
    
        string str(title);
    
        if(str == "Rechner")
        {
        	cout << "Rechner gefunden!" << endl;
        	if(IsWindowVisible(hWnd))
        		ShowWindow(hWnd, SW_HIDE);
        }
    
        return true;
    }
    

    funktioniert problemlos. Es flimmert kurz dort, wo das Fenster ist/war und dann verschwindet es, und ist nur noch in der Prozessliste der Taskmanagers zu sehen. Zum Testen eignet sich wohl besser ShowWindow(hWnd, SW_MINIMIZE); - auch das funktioniert und der Rechner findet sich in der Taskleiste wieder ...



  • Belli schrieb:

    funktioniert problemlos. Es flimmert kurz dort, wo das Fenster ist/war und dann verschwindet es, und ist nur noch in der Prozessliste der Taskmanagers zu sehen. Zum Testen eignet sich wohl besser ShowWindow(hWnd, SW_MINIMIZE); - auch das funktioniert und der Rechner findet sich in der Taskleiste wieder ...

    Offenbar ist dein Computer schneller als meiner beim Laden, denn der von dir gepostete Code funktioniert nur wenn ich vor IsWindowVisible(hWnd) eine Sleep(500) Funktion einbaue. 🙄

    Und hier wären wir wieder beim Thema.. wie lange benötigt das Fenster bis es vom Prozess angezeigt wird und vollständig sichtbar ist, denn zur Zeit der Abfrage ist das Fenster anscheinend zwar bereits am Laden jedoch nicht sichtbar, und kann somit nicht manipuliert werden. (ShowWindow)

    Hier Hilft auch kein erneuertes WaitForInputIdle vor der IsWindowVisible Abfrage einzubauen. 😞

    Und ich bräuchte eine Funktion um genau dieses Problem zu lösen 👍



  • Dann bin ich überfragt, laut MSDN

    The WaitForInputIdle function enables a thread to suspend its execution until a specified process has finished its initialization and is waiting for user input with no input pending.

    sollte der Prozess bereits in der Lage sein, User - Input anzunehmen, also sollte es nach der Rückkehr von WaitForInputIdle schon möglich sein, in das Eingabefeld zu tippen, mithin müsste das Fenster auch längst sichtbar sein ...

    Wenn das bei Dir nicht so ist, kann ich Dir nicht weiter behilflich sein.



  • Belli schrieb:

    Dann bin ich überfragt, laut MSDN

    The WaitForInputIdle function enables a thread to suspend its execution until a specified process has finished its initialization and is waiting for user input with no input pending.

    sollte der Prozess bereits in der Lage sein, User - Input anzunehmen, also sollte es nach der Rückkehr von WaitForInputIdle schon möglich sein, in das Eingabefeld zu tippen, mithin müsste das Fenster auch längst sichtbar sein ...

    Wenn das bei Dir nicht so ist, kann ich Dir nicht weiter behilflich sein.

    Danke dir für den Versuch 😃

    Edit: *kopf->tisch*.. mir ist gerade eingefallen, dass man einen Loop vor dem Anzeigen des Fensters einbauen kann:

    BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) 
    { 
        char title[512]; 
        GetWindowText(hWnd, title, sizeof(title)/sizeof(title[0])); 
        string str(title); 
    
        if(str == "Rechner") 
        { 
            cout << "Rechner gefunden!" << endl; 
    		int xx;
    		do {
    			xx++;
    			cout << xx << endl; //LADEZEIT ausgeben
    		} while (!IsWindowVisible(hWnd));
                    //NUN ist das Fenster auch sichtbar
                    ShowWindow(hWnd, SW_HIDE);
        } 
        return true; 
    }
    

    somit wartet das Programm bis auch das Fenster sichtbar / geladen ist 🙄



  • Naja, da hast Du aber eine busy-loop, das ist nicht besonders glücklich; ersetz das xx++ durch zB Sleep(20), dann kriegt die CPU zwischendurch ein bisschen Luft.



  • ersetz das xx++ durch zB Sleep(20), dann kriegt die CPU zwischendurch ein bisschen Luft

    nicht nur das, ich würd mir da noch nen timer einbauen, das gesetzt dem fall der process das fenster nicht erzeugt, dein prog. irgendwann selbst den weg aus der schleife findet. bzw. nachfrägt, ob es die schleife beenden darf o. nicht.


Anmelden zum Antworten