CreateProcess und dann Handle vom Fokus-Element?



  • GUITHREADINFO lpgui;
    
    ZeroMemory(&lpgui, sizeof(GUITHREADINFO)); // egal ob mit oder ohne init.!
    
    lpgui.cbSize = sizeof(GUITHREADINFO);
    
    ...
    
    bool rc = GetGUIThreadInfo(sProcessInfo->dwThreadId, &lpgui);
    if(rc == false)
    {
      // Fehler
      return -1;  // hier renn ich nich rein, Rückgabewert ist true!
    }
    ...
    HWND hwndFocus = lpgui.hwndFocus; // ist immer NULL!
    

    GetLastError (hab ich grad mal eingebaut) liefert 0, also ERROR_SUCCESS.



  • sieht eigentlich ganz vernünfig aus. 😕

    hab mal nen kleinen test geschrieben, bei funktioniert es wie ich beschrieben hatte. am besten du postest mal deinen relevanten code.

    mein test:

    int main(int argc, char *argv[])
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));
    
        if(!CreateProcess(
    		NULL,
            TEXT("notepad.exe"),
            NULL,
            NULL,
            FALSE,
            0,
            NULL,
            NULL,
            &si,
            &pi)) 
        {
    		cout << "CreateProcess failed < " << GetLastError() << " >" << endl;
    	        return -1;
        }
    
        // natürlich nicht die feine englische, aber für nen test geht's  ;) 
        WaitForSingleObject(pi.hProcess, 3000);
    
    	GUITHREADINFO gui;
    
    	ZeroMemory(&gui, sizeof(GUITHREADINFO));
    
    	gui.cbSize = sizeof(GUITHREADINFO);
    
    	if(!(GetGUIThreadInfo(pi.dwThreadId, &gui)))
    	{
    		cout << "GetGUIThreadInfo failed < " << GetLastError() << " >" << endl;
    	        return -1;
    	}
    
    	cout << "hwndFocus < " << gui.hwndFocus << " >" << endl;
    
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    
    	system("pause");
    
    	return 0;
    }
    


  • mmm... hab ich ja eigentlich ganz genauso...
    was meinste denn mit "relevantem code"?



  • el Clio schrieb:

    was meinste denn mit "relevantem code"?

    du funktionen die etwas mit dem problem zu tun haben 😉
    es ist zum beispiel völlig uninteressant welche child fenster du in deiner anwendung hast oder wie du auf wm_size reagierst, waren jetzt nur beispiele (falls es sich um eine winapi gui anwendung handelt) aber ich denke du weisst was ich meine. 😉



  • ach so...

    Na dann leg ich mal los! Vorab noch:Es ist alles noch nicht fertig, weil ich eben beim "hwndFocus" hängengeblieben bin.
    Ach so, erstellt hab ich den "Unsinn" übrigens mit BCB.

    // in meiner Formular-cpp
    HANDLE hTest;
    PROCESS_INFORMATION sProcessInfo;
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
       // Init der Variablen bzw. Anzeige
       Edit1->Text = "c:\\windows\\notepad.exe";
       Edit2->Text = "";
       hTest = NULL;  // Edit2 dient zur Statusanzeige!
       Button2->Enabled = false;
    
       ZeroMemory(&sProcessInfo, sizeof(PROCESS_INFORMATION));
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
       // starte Prog und prüfe, ob ok!
       if((hTest = ExecuteProcess(Edit1->Text, ExtractFilePath(Edit1->Text), &sProcessInfo)) != NULL)
       {
          Edit2->Text = "Prog läuft";
          Timer1->Enabled = true;
          Button2->Enabled = true;
       }
       else
       {
          // na sowas!
          Edit2->Text = "Prog NICHT gestartet!!!";
       }        
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
       if(hTest != NULL) // sollt immer ok sein!
       {
          DWORD noteExitCode; // hier werden gleich daten gespeichert
    
          // hole ExitCode und prüfe, ob Ausführung ok!
          if(GetExitCodeProcess(hTest,&noteExitCode))
          {
             if(noteExitCode == STILL_ACTIVE)
             {
                // immer noch an
                Edit2->Text = "Prog läuft noch!";
                Button2->Enabled = true;
             }
             else
             {
                // Programm beendet
                Timer1->Enabled = false;
                CloseHandle(hTest);
                Edit2->Text = "Prog beendet";
                Button2->Enabled = false;
             }
          }
       }        
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
       Edit3->Text = TextSend(hTest,&sProcessInfo,Edit3->Text);        
    }
    
    // in meiner CreateProcess.cpp (aus der FAQ des Boards übernommen und modifiziert)
    HANDLE ExecuteProcess( const String &CommandLine, const String &WorkDir, PROCESS_INFORMATION *sProcessInfo)
    {
       STARTUPINFO sStartInfo;
       ZeroMemory( &sStartInfo, sizeof(STARTUPINFO) );
       sStartInfo.cb = sizeof(STARTUPINFO);
       sStartInfo.wShowWindow = SW_SHOWDEFAULT;
       sStartInfo.dwFlags = STARTF_USESHOWWINDOW;
    
       bool ok = CreateProcess( NULL,
                                CommandLine.c_str(),
                                NULL,
                                NULL,
                                false,//true,
                                0,//NORMAL_PRIORITY_CLASS,
                                NULL,
                                NULL,//WorkDir.c_str(),
                                &sStartInfo,
                                sProcessInfo
                                );
    
       if(!ok)
       {
          sProcessInfo->hProcess = 0;
       }
    
       return sProcessInfo->hProcess; // zwar nicht mehr nötig, aber egal.
    }
    
    // in meiner Textsenden-cpp
    AnsiString TextSend(HANDLE hWin, PROCESS_INFORMATION *sProcessInfo, AnsiString text)
    {
       GUITHREADINFO lpgui;
    
       ZeroMemory(&lpgui, sizeof(GUITHREADINFO));
    
       lpgui.cbSize = sizeof(GUITHREADINFO);
    
       bool rc = GetGUIThreadInfo(sProcessInfo->dwThreadId, &lpgui);
       if(rc == false)
       {
          // Fehler
          return "Fehler!";
       }
    
       HWND hwndFocus = lpgui.hwndFocus;
       AnsiString ret;
       int nLen;
       if(hwndFocus != NULL)
       {
          // Länge des Textes holen
          nLen = SendMessage(hwndFocus, WM_GETTEXTLENGTH, 0, 0);
          char *pText = new char[nLen];
    
          // Text holen und speichern
          SendMessage(hwndFocus, WM_GETTEXT, (WPARAM)nLen, (LPARAM)pText);
          ret = pText;
    
          // Text modifizieren (im Moment einfaches ersetzen)
          ret = text;
    
          // Text in das Element zurückschreiben
          SendMessage(hwndFocus, WM_SETTEXT, 0, (LPARAM)(LPCTSTR)ret.c_str());
    
          return ret;
       }
       else
       {
          return AnsiString((int)hwndFocus); // nur zur Kontrolle, logischerweise immer NULL
       }
    }
    


  • Also ich blicks echt nich... Hat das was mit dem XP-SP2 zu tun, oder was? (Wär ja nich das erste mal!)
    Was mach ich denn falsch, dass das bei mir nicht klappt?



  • Ich krieg die Krise!

    Ich habe das bisher ja so gehabt, dass ich mit dem einen Button das Programm starte, und mit dem 2. Button die Funktion TextSend() aufrufe.
    In der TextSend() erhalte ich dann ständig NULL.
    Ich habe jetzt den Aufruf

    Edit3->Text = TextSend(hTest,&sProcessInfo,Edit3->Text);
    

    mit in die Button1Click() reingepackt, direkt nach Ausführung von Executeprocess().

    Und siehe da, es funktioniert!

    Problem: Das hilft mir nix, da ich ja auch zu späteren Zeitpunkten auf das andere Prog zugreifen will.
    Der Versuch, das andere Prog vorher in den Vordergrund zu holen klappt mit etForegroundWindow(hWin) bzw. etForegroundWindow(sProcessInfo->dwThreadId) auch nicht, das liefert immer false zurück!

    BITTE HELFT MIR!!!



  • 😃 welche buttons buttons du wie klickst wussteste ich natürlich nicht 😃

    el Clio schrieb:

    Problem: Das hilft mir nix, da ich ja auch zu späteren Zeitpunkten auf das andere Prog zugreifen will.

    was meinst du damit?
    ich hab es so verstanden das wenn deine app den focus wieder hat soll sie an den prozess den sie gestartet hat an das letzte aktive control eine nachricht schicken. richtig?



  • miller_m schrieb:

    was meinst du damit?
    ich hab es so verstanden das wenn deine app den focus wieder hat soll sie an den prozess den sie gestartet hat an das letzte aktive control eine nachricht schicken. richtig?

    Fast! Ich will das Prog starten und irgendwann - wann auch immer der Benutzer will - div. Nachrichten (u.A. auch Text) an die andere Anwendung schicken.
    Das soll solange möglich sein, bis meine oder die andere Anwendung geschlossen werden. Zwischendurch sollen beide Progs beliebig genutzt werden können.



  • wenn deine app aktiviert wird, müsstest du dir die handles holen und bei einem click auf einen "aktionsbutton" dann die aktion mit dem gespeicherten handle ausführen.



  • miller_m schrieb:

    wenn deine app aktiviert wird, müsstest du dir die handles holen und bei einem click auf einen "aktionsbutton" dann die aktion mit dem gespeicherten handle ausführen.

    Ich dachte eigentlich, dass ich genau das tue. 😉



  • und wo ist dann dein problem? oder ist jetzt alles ok?



  • Das Problem ist folgendes:

    Ich starte mit CreateProcess ein anderes Programm.
    Wenn ich direkt danach, also in der gleichen "Button-Funktion" GetGUIThreadInfo(sProcessInfo->dwThreadId, &lpgui) aufrufe bekomme ich in lpgui ein handle auf das "Fenster" mit dem Fokus.
    Soweit so gut, so solls auch sein!

    Wenn ich nach dem CreateProcess (ich speicher mir natürlich alle Strukturen und Handles) erst noch was anderes mit meiner anwendung mache und dann, zu einem späteren Zeitpunkt GetGUIThreadInfo(sProcessInfo->dwThreadId, &lpgui) aufrufe, dann ist in lpgui alles NULL ausser cbSize.
    Also ist auch der Handle vom Fokus-Fenster NULL und ich kann nicht mehr das machen, was ich will.

    Ich brauche also mal dringend nen Tip, wie ich zu nem späteren Zeitpunkt ein handle auf das element mit dem fokus kriege.

    Mag auch sein, dass ich nen Denkfehler drinhab oder so...


Anmelden zum Antworten