externes Programm automatisch beenden?



  • Hallo zusammen,
    ich möchte ein kleines C++ Programm schreiben, dass ein externes Spiel ausführt und nach einer gewissen Zeit automatisch wieder beendet. Ich stelle mir das ganze ungefähr so vor:

    int main() {
    system("spiel.exe");
    while (clock()/CLOCKS_PER_SEC < 3600);    //3600 als Bsp. für 1h Spielzeit
    // terminiere spiel.exe
    }
    

    Gibt es eine Konsoleneingabe, die diese Terminierung ausführt (dann könnte ich in dem Programm zum Beispiel 'system("terminate spiel.exe")' schreiben), oder eine andere Möglichkeit, um das Beenden von "spiel.exe" durchzuführen?



  • erstmal solltest du das spiel nicht mit system() starten (-> FAQ) sondern mit WinExec() oder ShellExecute() (alternativ auch CreateProcess() );

    zum Beenden kannst du zB WM_CLOSE an das Fenster senden, TerminateProcess ist für normales beenden des Prozesses nicht empfehlenswert;

    BspStarten:

    WinExec("C:\\test\\spiel.exe", SW_NORMAL);//pfad ersetzen!
    

    Bsp beenden:

    HWND spiel=FindWindow(0, TEXT("Fenstertitel Spielfenster"));//titel ersetzen!
    SendMessage(spiel, WM_CLOSE, 0, 0);
    

    lg,
    andi01.



  • Danke für die Antwort, ich werds direkt ausprobieren wenn ich wieder an meinem PC bin.
    Gibt es denn auch Möglichkeiten, dass ganze als Konsolenanwendung und nicht als Windowsanwendung zu programmieren? Ich komme mit Konsolenprogrammierung deutlich besser klar als mit Windowsprogrammierung.



  • klar, du wählst beim Erstellen deines Projektes statt Windowsanwendung einfach Konsolenanwendung aus.Wo du das genau machst hängt davon ab welche IDE du benutzt, ist aber bei allen sehr ähnlich, deshalb hier mal für Visual Studio:

    ->öffne VisualStudio
    ->Klicke auf Datei -> Neu-> Projekt
    ->Klicke im neuen Fenster links auf Visual C++ -> Win32
    -> Klicke im selben Fenster Rechts auf Konsolenanwendung
    ->tippe einen namen dafür ein und wähle den Speicherort
    ->Ok, Weiter,
    ->Unter Anwendungstyp Konsolenanwendung auswählen
    ->Unter Zusätzliche Optionen Haken bei Leeres Projekt setzen
    ->Fertig stellen

    ->im Projektmappenexplorer:
    ->Rechtsklick auf Quelldateien
    ->Hinzufügen->Neues Element
    ->in der linken Spalte Visual C++ -> Code auswählen
    ->Cpp-Datei (.cpp) auswählen
    ->namen eingeben
    ->ok

    --> da kommt der Code rein.

    meine Codebeispiele funktionieren natürlich auch in einer Konsolenanwendung.

    Welche IDE benutzt du?

    lg,
    andi01.



  • Ich benutze Dev-C++.
    Ich hab mit dem Ganzen ein bisschen rumgespielt und bin dabei auf ein paar Probleme gestoßen:

    1. FindWindow braucht einen Fenstertitel, um das Fenster zu finden. Wenn 'spiel.exe' aber eine Konsolenanwendung ist, wird dem doch gar kein neues Fenster zugewiesen, oder?

    Um dieses Problem zu umgehen, habe ich CreateProcess und TerminateProcess ausprobiert. Das klappt soweit ganz gut, aber ich bin mir nicht ganz sicher, was genau dabei passiert. Ich poste mal meinen Code (ungefähr, bin nicht an meinem Haupt-PC) und danach meine Fragen.

    int main(int argc, char *argv[]) {  //argv[1] muss das auszuführende Spiel, argv[2] die Spielzeit in Sekunden sein
    
    if (argc != 3) {
     // Fehlermeldung
     return 1;
    }
    
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    
    ZeroMemory( &si, sizeof(si) );  // x) 
    si.cb = sizeof(si);             // x) (siehe unten)
    ZeroMemory( &pi, sizeof(pi) );  // x)
    
    if (!CreateProcess(NULL, argv[1], /*...*/, si, pi) ) {
     //Fehlermeldung
     return 1;
    }
    Sleep(atoi(argv[2])*1000);
    if (GetExitCode(pi.hProcess) == STILL_ACTIVE) {
     if (!TerminateProcess(pi.hProcess, 1) ) {
      //Fehlermeldung
      return 1;
    }
    
    return 0;
    }
    

    Fragen:
    2. Wozu dienen die drei mit x) markierten Zeilen? Ich habe sie von hier übernommen, und CreateProcess funktioniert nicht ohne sie, aber ich verstehe ihren Sinn nicht.

    3. In pi ist auch ein handle pi.hthread enthalten, daher habe versucht, mir über Prozesse und Threads klarzuwerden, aber ich habe noch Probleme damit. Unter einem Prozess stelle ich mir einfach ein Programm vor, aber was genau ist ein Thread? Gibt es dafür ein Beispiel anhand einer bekannten Anwendung?

    4. Was genau passiert bei TerminateProcess? Das Programm 'spiel.exe' wird beendet, klar. Aber welche negativen Effekte treten dabei auf? Wird zum Beispiel der Speicher, den 'spiel.exe' benutzt, nicht wieder freigegeben oder ähnliches?

    Ich glaub, das wars erstmal. Danke schonmal für die Antworten.



  • Ich benutze Dev-C++

    nicht unbedingt die beste Wahl da DevC++ ziemlich veraltet ist, nicht mehr weiterentwickelt wird und einige bekannte bugs hat. zB Visual Studio 2010 Express oder Code::Blocks wären besser^^

    1. FindWindow braucht einen Fenstertitel, um das Fenster zu finden. Wenn 'spiel.exe' aber eine Konsolenanwendung ist, wird dem doch gar kein neues Fenster zugewiesen, oder?

    Auch ein Konsolenfenster hat einen Fenstertitel, den müsstest du einfach FindWindow übergeben. Und jedes normale Spiel sollte eigentlich ein Fenster haben^^

    . Aber welche negativen Effekte treten dabei auf? Wird zum Beispiel der Speicher, den 'spiel.exe' benutzt, nicht wieder freigegeben oder ähnliches?

    so ähnlich^^ zB mit globalen Dll-Daten gibt es u.U. Probleme, außerdem hat der Prozess keine Chance noch etwas vor dem Beenden zu tun was er unter Umständen tun würde wenn du den Schließbutton anklickst,...

    genaueres siehe msdn(zB hier unter Remarks): http://msdn.microsoft.com/en-us/library/ms686714(VS.85).aspx

    2. Wozu dienen die drei mit x) markierten Zeilen? Ich habe sie von hier übernommen, und CreateProcess funktioniert nicht ohne sie, aber ich verstehe ihren Sinn nicht.

    msdn schrieb:

    Fills a block of memory with zeros.

    -> überschreibt den Speicherblock mit Nullen. -> leer den Speicherblock

    3. In pi ist auch ein handle pi.hthread enthalten, daher habe versucht, mir über Prozesse und Threads klarzuwerden, aber ich habe noch Probleme damit. Unter einem Prozess stelle ich mir einfach ein Programm vor, aber was genau ist ein Thread? Gibt es dafür ein Beispiel anhand einer bekannten Anwendung?

    Ein Thread ist ein Teil eines Prozesses, Multithreading (also fdas Verwenden mehrerer Threads) dient dazu, bestimmte Codeteile "gleichzeitig" auszuführen (auch wenn das nicht ganz gleichzeitig passiert), fast wie in einem zweiten prozess.
    http://de.wikipedia.org/wiki/Thread_(Informatik)

    wikipedia schrieb:

    Ein Prozess bezeichnet den Ablauf eines Computerprogrammes auf einem Prozessor. [...] Threads teilen sich innerhalb eines Prozesses den Speicher und andere, betriebssystemabhängige Ressourcen wie Dateien und Netzwerkverbindungen.

    wikipedia schrieb:

    Ein Thread ist Teil eines Prozesses.

    Allerdings bräuchtest du dich eigentlich gar nicht mit dem Thema Threads zu beschäftigen weil man TerminateProcess nicht für normales beenden eines Prozesses nimmt, nur wenn er sich zB "aufgehängt" hat und zB auf normale Beendigungsversuche keine Reaktion zeigt.

    lg,
    andi01.



  • Statt auf die äußerst trivialen Fragen zu antworten gebe ich dir den Tipp, das selbst in der MSDN nachzulesen. Etwas Eigeninitiative musst du schon mitbringen.

    Edit: Zu spät 😞



  • hier mal einer von mehreren Wegen wie man den mit CreateProcess() gestarteten Prozess normal beenden könnte:

    DWORD pid;
    HWND fenster;
    
    BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lparam)
    {
        if(!IsWindowVisible(hwnd))
        {
            return true;
        }
    
        DWORD pid2;
        GetWindowThreadProcessId(hwnd, &pid2);
    
        if(pid==pid2)
        {
            fenster=hwnd;
            return false;//abbruch
        }
    
        return true;
    }
    
    int main()
    {
        PROCESS_INFORMATION pi;//letzter Parameter von CreateProcess()
        pid=pi.dwProcessId;
    
        EnumWindows(EnumProc, 0);
    
        SendMessage(fenster, WM_CLOSE, 0, 0);
    }
    

    lg,
    andi01.



  • Dein Code funktioniert super, vielen Dank!


Anmelden zum Antworten