ShellExecute - Fenster wieder schliessen



  • Wie kann ich genau das Fenster/Programm automatisch wieder schliessen, welches ich soeben mit ShellExecute erzeugt habe ?



  • Such mit FindWindow nach dem Fenster und schließe es mit WM_CLOSE oder mach einen Snapshot, such dir dein Programm raus (du kennst ja den Pfad und Anwendungsnamen) und schieß es dann mit TerminateProcess ab.



  • TerminateProcess... doch nicht sooo brutal ;), WM_CLOSE ist doch viel besser :).

    cya 🙂



  • Vielen Dank, doch einfach geht das nicht.
    Ich kann es nicht einfach mit WM_CLOSE schliessen, da ich den Programmpfad und die Parameter erst zur Laufzeit angebe (Variable).
    Und FinWindow hilft mir auch nicht viel weiter...da der Name nicht eindeutig ist und den Klassennname kann ich auch nicht angeben, da erst zur Laufzeit bekannt ist, um welche Anwendung es sich handeln soll.

    PS:
    Meist ist es so, das ich den IE verwende (also IEFrame).
    Allerdings will ich nicht einfach alle IEFrames schliessen, sondern nur genau das, welches geöffnet wurde.
    Das ist das Problem.



  • Ich mache sowas wie folgt: Ich starte den Prozess nicht per ShellExecute(), sondern mit CreateProcess(). Da bekommt man nämlich im letzten Parameter die ProcessId. Zum Schließen des Prozesses öffne ich zuerst den Prozess:

    // pID ist die Prozess-ID
    HANDLE hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pID);
    

    Dann enumeriere ich alle Fenster (EnumWindows()) und frage in der EnumWindowsProc ab, ob das Fenster zu dem Prozess gehört (GetWindowThreadProcessId()). Wenn ja, hole ich mir das Owner-Window (GetWindow() mit GW_OWNER), also das Main-Window, und schließe es per WM_CLOSE und danach nochmal (um sicher zu gehen) mit WM_SYSCOMMAND und SC_CLOSE. Dann warte ich (wieder in der Ausgangsfunktion) auf das Schließen des Prozesses per WaitForSingleObject(). Bekomme ich kein Signal, verwende ich halt den Hammer: TerminateProcess(). Am Ende dann nochmal CloseHandle() mit dem Handle als Parameter, das ich von OpenProcess() zurückgegeben bekommen hatte.

    [ Dieser Beitrag wurde am 11.03.2003 um 13:32 Uhr von WebFritzi editiert. ]



  • Vielen Dank erstmal für die Hilfe.
    Boah...also ich habe vorher nur C++ in Konsole und ein ganz kleines bisschen im BCB4 (VCL) was gemacht.
    Deshalb ist das jetzt ganz schön hart, was Du mir erzählst, WebFritzi 😉 .

    Also, ich habe es Probiert und bin bei folg. Problem hängen geblieben:
    Ich finde die ProcessID in pi nicht.
    Laut Definition von ProcessInformation müsste das doch dwProcessID sein....

    char parameter[256];
    char command[256]="c:\\programme\\internet explorer\\iexplore.exe ";
    strcpy(parameter,Edit1->Text.c_str());
    strcat(command, parameter);
    
    TStartupInfo si;
    TProcessInformation pi;
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    
    if(CreateProcess(NULL, command,
                    NULL,NULL,false,
                    CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
                    NULL,"c:\\",
                    &si, &pi)==false)
    Caption="Fehler beim Ausführen";
    //Sleep(1000);
    
    HANDLE hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, pi.dwProcessID);
    


  • Original erstellt von fit:
    Laut Definition von ProcessInformation müsste das doch dwProcessID sein....[/code]

    Nein, sondern dwProcessId. In C(++) unterscheiden wir zwischen Klein- und Großschreibung. Und bitte benutze STARTUPINFO und PROCESS_INFORMATION statt den Borland-Struktur-Namen.



  • Meine Unit:

    Die Header-Datei:

    //---------------------------------------------------------------------------
    #ifndef AppTerminatingH
    #define AppTerminatingH
    //---------------------------------------------------------------------------
    #include <windows.h>
    //---------------------------------------------------------------------------
    
    // Ein paar Definitionen
    #define TA_FAILED        0
    #define TA_CANNOT_OPEN   1
    #define TA_SUCCESS_CLEAN 2
    
    #define KA_FAILED        0
    #define KA_CANNOT_OPEN   1
    #define KA_SUCCESS_KILL  2
    //---------------------------------------------------------------------------
    
    BOOL CALLBACK TerminateAppEnum(HWND hwnd, LPARAM lParam);
    WORD TerminateAppByWindowClosing(DWORD pID, DWORD dwTimeout);
    WORD KillApp(DWORD pID);
    //---------------------------------------------------------------------------
    #endif
    

    Die C(PP)-Datei

    //---------------------------------------------------------------------------
    #include "AppTerminating.h"
    //---------------------------------------------------------------------------
    
    // Die WindowEnumProc zum Auffinden des Hauptfensters
    // des zu schließenden Prozesses
    BOOL CALLBACK TerminateAppEnum(HWND hwnd, LPARAM lParam)
    {
       static DWORD dwID;
       static HWND  hwnd_Owner;
    
       GetWindowThreadProcessId(hwnd, &dwID);
    
       if(dwID == (DWORD)lParam)
       {
          hwnd_Owner = GetWindow(hwnd, GW_OWNER);
          if(!hwnd_Owner) // Das Fenster ist das oberste im Prozess
          {
             PostMessage(hwnd, WM_CLOSE, 0, 0);
             PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
             return FALSE;  // Nicht mehr weiter enumerieren
          }
       }
    
       return TRUE;
    }
    //---------------------------------------------------------------------------
    
    // Funktion zum Schließen des Haupt-Fensters des Prozesses
    WORD TerminateAppByWindowClosing(DWORD pID, DWORD dwTimeout)
    {
       HANDLE  hProc;
       WORD    wRet;
    
       // Wir versuchen, den Prozess "clean" zu terminieren
       // durch Schließen des Haupt-Fensters
       EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM)pID);
    
       // Wenn wir den Prozess nicht mit SYNCHRONIZE-Rechten,
       // öffnen können, geben wir auf
       hProc = OpenProcess(SYNCHRONIZE, FALSE, pID);
       if(!hProc)
          return TA_CANNOT_OPEN;
    
       // Wir schauen, ob der Prozess geschlossen worden ist und warten
       // dabei dwTimeout Millisekunden
       if(WaitForSingleObject(hProc, dwTimeout) == WAIT_OBJECT_0)
          wRet = TA_SUCCESS_CLEAN;
       else
          wRet = TA_FAILED;
    
       CloseHandle(hProc);
    
       return wRet;
    }
    //---------------------------------------------------------------------------
    
    // Funktion zum Abwürgen des Prozesses
    // ACHTUNG: Alle DLLs, die mit dem Prozess verbunden sind,
    // werden nicht davon benachrichtigt, dass der Prozess
    // beendet wurde !!!
    WORD KillApp(DWORD pID)
    {
       HANDLE  hProc;
       WORD    wRet;
    
       // Wenn wir den Prozess nicht mit PROCESS_TERMINATE-Rechten
       // öffnen können, geben wir sofort auf
       hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pID);
       if(!hProc)
          return KA_CANNOT_OPEN;
    
       wRet = (WORD)( TerminateProcess(hProc,0) ? KA_SUCCESS_KILL : KA_FAILED );
    
       CloseHandle(hProc);
    
       return wRet;
    }
    //---------------------------------------------------------------------------
    

    Damit kannst du jetzt z.B. einen Notepad-Prozess schließen (klar - geht auch direkt mit WM_CLOSE):

    DWORD pID  = 0;
    HWND  hEditor = NULL;
    WORD  wTA;
    
    hEditor = FindWindow(NULL, "Unbenannt - Editor");
    if(!hEditor)
    {
       MessageBox(hwnd, "Fenster nicht gefunden", "ERROR", MB_OK);
       return;
    }
    
    GetWindowThreadProcessId(hEditor, &pID);
    wTA = TerminateAppByWindowClosing(pID, 5000);
    
    if(wTA != TA_SUCCESS_CLEAN)
    {
       char* buf1 = "Der Prozess konnte nicht durch bloßes Schließen des\nFensters beendet werden. Wollen Sie ihn killen?";
       char* buf2 = "Der Prozess konnte nicht gekillt werden";
       char* buf3 = "Der Prozess konnte nicht geöffnet werden";
    
       if(wTA == TA_CANNOT_OPEN)
          MessageBox(hwnd, buf3, "ERROR", MB_OK|MB_ICONERROR);
       else
       {
          INT resp = MessageBox(hwnd, buf1, "Information", MB_YESNO | MB_ICONINFORMATION);
          if(resp == IDYES)
             if(KillApp(pID) == TA_FAILED)
                MessageBox(hwnd, buf2, "Fehler", MB_OK|MB_ICONERROR);
       }
    }
    

Anmelden zum Antworten