Process erstellen und wieder schließen (CreateProcess)



  • Hi, ich bin ziemlich neu (eigentlich total neu) in c++. Deshalb brauche ich zunächst etwas hilfe:
    Ich möche eine datei (D:\\start.bat) starten und dann wieder schließen.
    Diese datei wird allerdings öfters (bis zu 5 mal gleichzeitig) gestartet (und bleibt geöffnet).

    Ich brauche eigentlich nur folgende infos:

    Wie kann ich mit CreateProcess() einen prozess starten (finde nichts gescheites zu den benötigten argumenten, also bitte mit ausgefüllten argumenten antworten) von dem ich irgendeine ID oder ähnliches bekomm (also bla=createprocess()), damit ich ihn später mit einer Funktion (leider finde ich diese nicht mehr) beenden kann (z.b. killtask(id)).

    Wäre klasse, wenn mir jemand helfen könnte.

    MfG Krauzi



  • Du hast gesucht?

    Sobald ich in Google "CreateProcess C++" eingebe, füttert er mich mit tausend Sachen, und dabei waren die ersten 3 Treffer ein Erfolg...

    http://www.goffconcepts.com/techarticles/development/cpp/createprocess.html

    http://www.wer-weiss-was.de/theme158/article3952000.html

    http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx

    http://forum.chip.de/c-c/problem-createprocess-462258.html

    http://forum.chip.de/c-c/wier-verwende-createprocess-468487.html

    http://board.gulli.com/thread/1223465-c-createprocess/

    http://www.tutorials.de/forum/c-c/261873-problem-mit-createprocess.html

    Hi, ich bin ziemlich neu (eigentlich total neu) in c++.

    Mich beunruhigt dieser Satz, sonst wird das nur eine C&P-Geschichte...

    Lg Mentras



  • Hm ich habe nach c++ createprocess gesucht und leider nichts wirklich gutes bekommen (keine erklärung der argumente bzw. dafür).

    Könnte mir nicht einfach jemand erklären, wie ich createprocess richtig verwende?

    Jedes mal wenn ich den code von http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx verwende kommt:

    test.exe funktioniert nicht mehr!
    Es wird nach einer lösung für das problem gesucht.

    Wenn man sich die o.g. links mal anschaut, liest man meist: ich habe die argumente nicht verstanden, könnte man mir die bitte mal erklären.

    Genauso geht es mir. Bitte erklärt mir einer einfach die argumente, oder schreibt mir nen code zum starten der D:\\start.bat (mit createprocess, evtl auch wie ich ihn dannach wieder schließe).



  • Hier etwas leichteres...

    #include <iostream>
    using namespace std;
    
    int main()
    {
    system("notepad.exe");
    }
    


  • C kennt zwar optionale Parameter, aber das hat sich noch nicht bis zu den Windows-Entwicklern herumgesprochen.
    Deshalb muss man eben nachschlagen und "leere Werte" übergeben, wenn man einen Parameter nicht bracht: meistens NULL oder sowas.

    Von deinem MSDN-Link abgeschrieben:

    #include <windows.h>
    
    int main(int argc, char *argv[])
    {
    
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
    
        CreateProcess( NULL,   // No module name (use command line)
            "cmd.exe /c c:\\start.bat",        // Command line
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            0,              // No creation flags
            NULL,           // Use parent's environment block
            NULL,           // Use parent's starting directory 
            &si,            // Pointer to STARTUPINFO structure
            &pi );           // Pointer to PROCESS_INFORMATION structure 
    
        return 0;
    }
    


  • #include <iostream>
    using namespace std;
    
    int main()
    {
    system("notepad.exe");
    }
    

    Obwohl das einer der ganz wenigen Fälle ist, wo man sowieso eine Shell starten muss: gewöhn dir das lieber nicht an.

    EDIT:
    Lies auch mal das:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-227972-and-postdays-is-0-and-postorder-is-asc-and-highlight-is-createprocess-and-start-is-10.html



  • Mentras schrieb:

    Hier etwas leichteres...

    #include <iostream>
    using namespace std;
    
    int main()
    {
    system("notepad.exe");
    }
    

    autsch, das ist ja überhaupt nicht das, wo nach ich suche. für sowas reichen sogar meine wenigen c kentnisse aus :D. Das problem ist (ich erklärs jetzt mal gaaaanz ausführlich):

    Es gibt einen Warcraft3 Hosting bot (GHost++ in c++ geschrieben http://forum.codelain.com) mit dem live streamen mit WaaaghTV möglich ist.
    Das problem ist nur, dass das programm WaaaghTV (das sich in das spiel einklinkt und dann live mit schaut) nicht die spiele liste (also die spiele, die mit GHost++ gehostet worden sind) aktuallisiert. Also muss ich für jedes spiel, dass vom Ghost gehostet wurde eigens die waaaghtv.exe starten. Nur logischerweise ist ein spiel auf irgendwann mal vorbei und dann muss die waaaghtv.exe wieder geschlossen werden. Da aber auch mehrere Spiele gleichzeitig geöffnet werden können brauche ich auch für jedes gehostete spiel eine eigene waaaghtv.exe.
    Wenn jetzt aber ein spiel wieder zu ende ist muss auch (bzw. DARF) nur die dazugehörige exe geschlossen werden.
    Im Ghost++ gibts für jedes geöffnete spiel eine klasse, in der ich eine variable (nennen wir sie processid) habe. Diese wird von CreateProcess bestimmt.
    Wenn ein spiel vorbei ist, lasse ich einfach DeleteProcess (wenns das gibt) mit der processid ausführen. Dann wird also nur die waaaghtv.exe geschlossen, zu der auch das abgeschlossene spiel gehört.
    Deshalb bringt mir system("befehl"); gar nichts, weil ich hier nie eine eindeutige ID bekom.

    EDIT: Der Code gibt mir zumindest schon mal <null> aus:

    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    
    void _tmain( int argc, TCHAR *argv[] )
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );
    
    	printf("processid: %s", CreateProcess(TEXT("WaaaghTVRecorder"), TEXT("D:\\Programme\\wc3tv\\start.bat"), NULL, NULL, TRUE, HIGH_PRIORITY_CLASS, NULL, TEXT("D:\\Programme\\wc3tv\\"), &si, &pi));
    
    	return;
    }
    


  • Der Code gibt mir zumindest schon mal <null> aus:

    Weil die PID in die PROCESS_INFORMATION-Struktur geschrieben wird.
    Aber bedenke: du bekommst nur die PID für den cmd.exe-Prozess, der dann das Batchfile ausführt.
    Besser wär's wahrscheinlich, deine waaaghtv.exe ohne den Umweg über die Batchdatei zu starten, weil's Overhead spart und du gleich die PID für den eigentlich wichtigen Prozess bekommst.

    Nachdem ich mit Windows nicht so wirklich auskenne, und hier schon wieder die system()-Kommentare kommen, rate ich dir, im WinAPI-Forum nachzufragen.



  • mngbd schrieb:

    Weil die PID in die PROCESS_INFORMATION-Struktur geschrieben wird.

    ähm und das heißt?

    mngbd schrieb:

    Aber bedenke: du bekommst nur die PID für den cmd.exe-Prozess, der dann das Batchfile ausführt.
    Besser wär's wahrscheinlich, deine waaaghtv.exe ohne den Umweg über die Batchdatei zu starten, weil's Overhead spart und du gleich die PID für den eigentlich wichtigen Prozess bekommst.

    Da man ja bei CreateProcess auch einen startpfad eingeben kann, kann ich mir die bat sowieso sparen. Nur wie zum Teufel bekomm ich eine ID mit der ich was anfangen kann (z.b. mit der ich später die waaagthtv.exe eindeutig identifizieren und schließen kann)?

    EDIT: Direkt EXE start würde dann so ausschauen:

    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    
    void _tmain( int argc, TCHAR *argv[] )
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        //ZeroMemory( &si, sizeof(si) );
        //si.cb = sizeof(si);
        //ZeroMemory( &pi, sizeof(pi) );
    
    	printf("processid: %s", CreateProcess(TEXT("WaaaghTVRecorder"), TEXT("D:\\Programme\\wc3tv\\wtvRecorder.exe"), NULL, NULL, TRUE, HIGH_PRIORITY_CLASS, NULL, TEXT("D:\\Programme\\wc3tv\\"), &si, &pi));
    
    	return;
    }
    


  • Krauzi schrieb:

    mngbd schrieb:

    Weil die PID in die PROCESS_INFORMATION-Struktur geschrieben wird.

    ähm und das heißt?

    mngbd schrieb:

    Aber bedenke: du bekommst nur die PID für den cmd.exe-Prozess, der dann das Batchfile ausführt.
    Besser wär's wahrscheinlich, deine waaaghtv.exe ohne den Umweg über die Batchdatei zu starten, weil's Overhead spart und du gleich die PID für den eigentlich wichtigen Prozess bekommst.

    Da man ja bei CreateProcess auch einen startpfad eingeben kann, kann ich mir die bat sowieso sparen. Nur wie zum Teufel bekomm ich eine ID mit der ich was anfangen kann (z.b. mit der ich später die waaagthtv.exe eindeutig identifizieren und schließen kann)?

    EDIT: Direkt EXE start würde dann so ausschauen:

    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>
    
    void _tmain( int argc, TCHAR *argv[] )
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
    
        //ZeroMemory( &si, sizeof(si) );
        //si.cb = sizeof(si);
        //ZeroMemory( &pi, sizeof(pi) );
    
    	printf("processid: %s", 
    		CreateProcess(TEXT("WaaaghTVRecorder"), 
    			TEXT("D:\\Programme\\wc3tv\\wtvRecorder.exe"), 
    			NULL, 
    			NULL, 
    			TRUE, 
    			HIGH_PRIORITY_CLASS, 
    			NULL, 
    			TEXT("D:\\Programme\\wc3tv\\"), 
    			&si, 
    			&pi)
    	);
    
    	return;
    }
    

    EDIT: ähm kacke, da hab ich wohl zitieren anstatt von editieren geklickt :-/.

    EDIT2: Es scheint, als würde CreateProcess nichts "returnen", PROCESS_INFORMATION pi wird bei jedem test.exe aufruf immer neu erstellt.



  • ähm und das heißt?
    [...]
    Nur wie zum Teufel bekomm ich eine ID mit der ich was anfangen kann (z.b. mit der ich später die waaagthtv.exe eindeutig identifizieren und schließen kann)?

    CreateProcess schreibt die Daten, die du suchst, in die Struktur:

    PROCESS_INFORMATION pi;
    

    Und zwar die Process ID (PID) in den Member pi.dwProcessId .
    Siehe http://msdn.microsoft.com/en-us/library/ms684873(VS.85).aspx

    Aber lass die beiden ZeroMemory's stehen!
    Wenn Microsoft das so will, dann muß es eben sein, sonst könnte alles mögliche passieren.
    Besonders si.cb = sizeof(si); sieht so aus, als ob sich CreateProcess darauf verlassen würde.



  • wenn ich allerdings auch ZeroMemory bei pi mache, ist der immer null. Irgendwie bekomm ich einfach keine gescheite id.

    EDIT: irgendwie sind alle process_information attribute null 😞 (nach CreateProcess).



  • Du musst aber schon auch aufpassen, was für Fehlermeldungen gemacht werden:

    #include <windows.h>
    
    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, "notepad.exe", NULL, NULL, FALSE,
                0, NULL, NULL, &si, &pi )) {
            printf("CreateProcess ging schief wegen Fehler Nr. %d", GetLastError());
            // siehe http://msdn.microsoft.com/en-us/library/ms680582%28VS.85%29.aspx
            return 1;
        }
    
        printf("Alles ok, PID=%d\n", pi.dwProcessId);
    
        return 0;
    }
    


  • Und nicht vergessen die beiden Handles von PROCESS_INFORMATION wieder zu schliessen.

    Simon



  • Genau...
    Huh, das wird langsam kompliziert:
    (siehe http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx )

    // ...
        printf("Alles ok, PID=%d\n", pi.dwProcessId);
    
        // Close process and thread handles. 
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
    
        return 0;
    }
    


  • hm, jetzt dachte ich mal daran, einen process nach einer bestimmten zeit wieder zu schließen.
    also habe ich pi.hProcess in ein array geschrieben. ich habe jetzt mehrere processes erstellt und auch deren pi.hProcess ins array gehaut.

    Um später alles zu schließen wollte ich eine for schleife verwenden, die dann mit TerminateProcess(array[i], 0); alle wieder beendet.
    Nur gibts jetzt einen int to HANDLER fehler.
    Jemand eine ahnung wie ich die processes später wieder schließen kann?



  • Den Zugriff auf den laufenden Prozess kriegst du erst, wenn du dir ein HANDLE mit OpenProcess geholt hast.
    (Kümmert sich um wichtige Dinge, wie ob du überhaupt das Recht dazu hast.)

    Es wäre aber wahrscheinlich klüger, dein Programm nicht die ganze Zeit laufen zu lassen, sondern nach dem Starten der gewünschten Prozesse einfach wieder zu beenden.

    Prinzipiell kannst du Prozesse auch einfach mit taskkill /pid:nnnn versenken.
    Die PID's kannst du dir ja in einer Datei aufheben oder zur Not auch mit tasklist herausfinden.



  • jop mit taskkill würde es klappen, nur würde ich es gerne mit openprocess machen, weil es mir irgendwie profesioneller und auch sicherer vorkommt, denn die wtvrecorder.exe muss erst einmal intialisieren und das dauert ein paar sekunden, erst dannach ist ein taskkill möglich (was allerdings soweit schon recht gut klappt).

    Zu Openprocess: Ich benötige hier ein beisspiel (ich finde auf der microsoft site überhaupt nichts / bzw google).



  • das ganze gewurschtel mit bat-dateien sieht mir nach nem fehlkonzept aus.
    seis drum. als einfachste lösung fällt mir da ein: wie wäre es mit einem eigenen thread pro batfile-aufruf, man muss ja nicht gleich mit kanonen auf spatzen schiesen?

    void start_bat( void *nix )
    {
    	system("batfile.bat");
    }
    
    #include <process.h>
    
    int main() 
    { 
    	int i;
        for (i=0; i<5; i++)
    		if ( 0>_beginthread(start_bat,0,NULL))
    			break;
        if (i != 5)
    		puts("Konnte nicht alle Threads starten!");
    	system("PAUSE"); 
        return 0; 
    }
    


  • konzept0r schrieb:

    das ganze gewurschtel mit bat-dateien sieht mir nach nem fehlkonzept aus.

    das mit der batch ist schon geschichte. habe das nur als beispiel datei geschrieben.

    Nur möchte ich das jetzt unbedingt mit OpenProcess machen.

    Folgende situation:
    Ich habe eine program id (angenommen 45623) und möchte jetzt das zugehörige programm ohne system("taskkill /pid:45623") schließen.

    Wie mache ich das, wenn ich OHNE den createprocess anfange (also ich kein Process_information und startup_info habe)?

    EDIT:
    So geht das xD:

    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processid);
    TerminateProcess(hProcess, 0);
    

Anmelden zum Antworten