Forum: PC-Programmierung Exitcodes spawn(), system() [Win32, c]


von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Servus,

ich möchte von meinem Programm aus ein anderes (in diesem Fall
7z.exe) aufrufen und benötige dessen exit-Code und das, was es
auf die console ausgibt.

Mit
1
system( "7x e gaga.zip >datei")
erhalte ich das Ergebnis (zB die Dateiliste) in datei. Ok.
system gibt mir aber nicht 7z's exitcode zurück sondern den des
Kommandoprozessors. Klar kann ich diese Datei auswerten, ist aber
nicht sehr elegant und fehlerträchtug (zB Sprachwechsel).

Mit
1
spawnv( P_WAIT, "7z", ...parameterliste...);
bekomme ich den Exitcode von 7z aber nicht dessen console-output.
Eine Umleitung der Ausgabe in eine Datei geht dort nicht, das
macht ja der Kommandoprozessor ....

Gibt es da noch einen anderen Weg ?

von Peter II (Gast)


Lesenswert?

Joachim Drechsel schrieb:
> Gibt es da noch einen anderen Weg ?

mit createprocess arbeiten und die ausgabe selber in eine Datei 
umleiten.

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Merci. Ich stöbere mal ...

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Servus Peter,

es hat jetzt ein wenig gedauert bis es funktionierte. Ich habe mir
dazu das halbe Web durchwühlt und das was unten steht blieb übrig ;)

cmd ist die auszuführende Kommandozeile.

Unklar ist mir noch ob und welche Handles ich closen muß.
Werden mit CreatePipe() noch andere Sachen geöffnet ?
Muß ich die Pipe auch irgendwie schließen ?
1
#define BUFSIZE 4096
2
3
HANDLE rPipe = NULL;
4
HANDLE wPipe = NULL;
5
char   chBuf[BUFSIZE];
6
7
        int
8
        JExecute(
9
        char    *cmd
10
        )
11
{
12
        SECURITY_ATTRIBUTES saAttr;
13
        PROCESS_INFORMATION piProcInfo;
14
        STARTUPINFO         siStartInfo;
15
        BOOL    bSuccess;
16
        int     code = 255;
17
18
        fprintf( fprt, "\n        executing %s", cmd);
19
        *chBuf = 0;
20
21
        // Set the bInheritHandle flag so pipe handles are inherited
22
        saAttr.nLength              = sizeof(SECURITY_ATTRIBUTES);
23
        saAttr.bInheritHandle       = TRUE;
24
        saAttr.lpSecurityDescriptor = NULL;
25
26
        // Create a pipe for the child process's STDOUT
27
        if ( ! CreatePipe(&rPipe, &wPipe, &saAttr, 0))
28
                ExitError( "uimpxml", "CreatePipe() - pipe for child process\'s STDOUT failed");
29
30
        // Ensure the read handle to the pipe for STDOUT is not inherited
31
        if ( ! SetHandleInformation(rPipe, HANDLE_FLAG_INHERIT, 0))
32
                ExitError( "uimpxml", "SetHandleInformation() - pipe STDOUT read handle failed for inheritance");
33
34
        ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
35
36
        ZeroMemory( &siStartInfo, sizeof( STARTUPINFO));
37
        siStartInfo.cb         = sizeof( STARTUPINFO);
38
        siStartInfo.hStdError  = wPipe;
39
        siStartInfo.hStdOutput = wPipe;
40
        siStartInfo.hStdInput  = NULL;
41
        siStartInfo.dwFlags   |= STARTF_USESTDHANDLES;
42
43
        // Create the child process
44
        bSuccess = CreateProcess(
45
          NULL, // Use szCmdLine
46
          cmd,  // command line
47
          NULL, // process security attributes
48
          NULL, // primary thread security attributes
49
          TRUE, // handles are inherited
50
          0,    // creation flags
51
          NULL, // use parent's environment
52
          NULL, // use parent's current directory
53
          &siStartInfo, // STARTUPINFO pointer
54
          &piProcInfo); // receives PROCESS_INFORMATION
55
56
        if ( bSuccess) {
57
                WaitForSingleObject( piProcInfo.hProcess, INFINITE);
58
                GetExitCodeProcess( piProcInfo.hProcess, (LPDWORD) &code);
59
                CloseHandle( piProcInfo.hProcess);
60
                CloseHandle( piProcInfo.hThread);
61
        }
62
63
        ReadFromPipe();
64
65
        CloseHandle( rPipe);
66
        CloseHandle( wPipe);
67
68
        return code;
69
}
70
71
        // Read output from the child process's pipe for STDOUT and
72
        // write to the parent process's pipe for STDOUT. Stop when
73
        // there is no more data.
74
75
        void
76
        ReadFromPipe()
77
{
78
        DWORD   dwRead;
79
        BOOL    bSuccess = FALSE;
80
        int     i;
81
82
        CloseHandle( wPipe);
83
84
        fprintf( fprt, "\n        > ");
85
        for( ; ; ) {
86
                bSuccess = ReadFile( rPipe, chBuf, BUFSIZE, &dwRead, NULL);
87
                if(!bSuccess || dwRead == 0)
88
                        break;
89
                for ( i=0; i<dwRead; i++){
90
                        switch ( chBuf[i]) {
91
                          case '\r':
92
                                break;
93
                          case '\n':
94
                                fprintf( fprt, "\n        > ");
95
                                break;
96
                          default     : ;
97
                                fputc( chBuf[i], fprt);
98
                        }
99
                }
100
        }
101
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Joachim Drechsel schrieb:
> Muß ich die Pipe auch irgendwie schließen ?

Das machst Du doch:

>   CloseHandle( rPipe);
>   CloseHandle( wPipe);

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Das reicht ? Ich hatte so irgendwie das Gefühl, da sei wieder
irgendwo noch ein kleines Unheil ...

Die Funktion wird uU einige 100mal hintereinander aufgerufen,
nicht, daß ich da irgendwelche Leaks hineinbekomme.

Merci !

von Peter II (Gast)


Lesenswert?

Joachim Drechsel schrieb:
> Die Funktion wird uU einige 100mal hintereinander aufgerufen,
> nicht, daß ich da irgendwelche Leaks hineinbekomme.

dann schau doch einfach in den Taskmanager nach. Dort kann man die 
Spalte Handles anzeigen. Wenn der wert nicht steigt ist alles ok.

von Joachim D. (Firma: JDCC) (scheppertreiber)


Lesenswert?

Peter II schrieb:
> dann schau doch einfach in den Taskmanager nach. Dort kann man die
> Spalte Handles anzeigen. Wenn der wert nicht steigt ist alles ok.

Bleibt gleich (wenn die Anzeige stimmt) ;)

Ich lasse das mal unter Last laufen. Mal schauen was da heraus kommt. 
:-)

Vielen Dank an euch alle !

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.