NSLog geht nicht mehr nach NSTask und setStandardError

  • NSLog geht nicht mehr nach NSTask und setStandardError

    Hallo zusammen,

    ich bin neu hier und auch erst seit ein paar Wochen mit Obj C und Cocoa unterwegs. Hab schon einiges gelernt, v.a. weil es so tolle Foren gibt wie dieses hier. Weshalb dieser Code jedoch nicht geht, versteh ich nicht.

    Was geht nicht? Nach der Ausführung diese Codes ist NSLog kaputt, gibt nichts mehr in der Konsole aus. Irgendwie scheint NSLog der stderr verloren gegangen zu sein. Was mach ich hier falsch? Ich release doch die Pipe wieder! Auch ist's ja nur der stderr für den Task, den ich setze.

    - (void)executeShellScript:(NSString*)path withArgs:(NSArray*)args {
    NSLog(@"Entry");
    NSString *fullpath = [path stringByExpandingTildeInPath];
    NSFileManager *fm = [NSFileManager defaultManager];
    if ([fm fileExistsAtPath:fullpath]) {
    NSTask *shellProcess = [[NSTask alloc] init];
    NSPipe *errorPipe = [NSPipe pipe];
    //NSPipe *errorPipe = [[NSPipe alloc] init];
    [shellProcess setLaunchPath:fullpath];
    [shellProcess setArguments:args];
    [shellProcess setStandardError:errorPipe];
    [shellProcess launch];
    NSData *result = [[errorPipe fileHandleForReading] readDataToEndOfFile];
    if ([result length]>1) {
    NSString *error = [[NSString alloc] initWithData:result encoding:NSASCIIStringEncoding];
    [self showErrMsg:error];
    [error release];
    }
    NSLog(@"Pipe open");
    //[errorPipe release];
    [shellProcess release];
    NSLog(@"Pipe and task closed");
    }
    else {
    NSString *error = [fullpath stringByAppendingString:@": File does not exist"];
    [self showErrMsg:error];
    }
    NSLog(@"Cheerio Miss Sophie");
    }


    NSLog gibt nur "Entry" aus. Dann ist Schluß. Die Applikation muß neu gestartet werden, damit es wieder funktioniert.

    Eine Idee? Die Doku für NSTask setStandardError ist ein bißchen arg kryptisch für einen Anfänger: If file is an NSPipe object, launching the receiver automatically closes the read end of the pipe in the current task. Don’t create a handle for the pipe and pass that as the argument, or the read end of the pipe won’t be closed automatically. ???
  • RE: NSLog geht nicht mehr nach NSTask und setStandardError

    Lies mal in der Doku (an gleicher Stelle wie Dein Zitat) unter "-standardError":
    andard error is where all diagnostic messages are sent. The object returned is either an NSFileHandle or an NSPipe instance, depending on what type of object was passed to setStandardError:.

    Alle Meldungen von NSLog gehen nach dorthin.
    Der Weg, Dein problem zu verhindern, ist einfach. Frage das Objekt mit oben genannter Methode ab und setze es mit 'setStandardError' wieder zurück, wenn Du mit Deiner Implementierung fertig bist.

    Achja, und benutze die 'tags' für 'code' und 'quote' die dieses Forum so angenehm machen!
    I would be embarrassed if they did not spy on me.
  • Das scheint nicht zu klappen. Das vorherige Sichern der Werte durch id oldErr =[shellProcess standardError] und das nachherige Zurückschreiben mit [shellProcess setStandard Error:oldErr] nach [shellProcess launch] hat nichts gebracht. Mir ist auch nicht klar, warum das was bringen sollte. Das dazugehörige NSTask Objekt wurde ja frisch allokiert und initialisiert. Mit setStandardError biege ich mir den stdErr dieses NSTask Objekts um, um (in meinem Fall) Fehler bei der Ausführung eines Shell-Scripts auswerten zu können und schön in einem NSTextView darstellen zu können. Das Umbiegen des stdErr des NSTask Objekts dürfte doch aber keinen Einfluß auf den stdErr der gesamten Applikation haben. NSLog müßte trotzdem weiter funktionieren. Tut's aber nicht. Selbst nach [shellProcess release]. Was also tun bzw. was mache ich (immer noch)falsch? Oder steh ich gerade auf dem Schlauch?
  • Ich denke, dass Du mit Deinen Ausführungen hier Recht hast.
    Was mir danach auffiel: Du gibst DeinNSTask-Objekt mit

    Quellcode

    1. [shellProcess release];
    frei, ohne dass irgendwie irgendwo der Status abgefragt ist.
    Man sollte es erst frei geben, wenn wirklich sicher ist, dass der aufgerufene Porzess beendet ist.
    Etwas aus der Richtung '-terminate', '-isRunning' etc. In der Doku steht ein gutes Beispiel.

    HTH

    longW
    I would be embarrassed if they did not spy on me.
  • Ok. Bin nun etwas weiter gekommen. Die obige Methode dient ja dazu, dass man ihr einfach einen Pfadnamen übergibt, der dann in der Kommandozeile ausgeführt wird. Dass NSLog nicht geht liegt daran, was ich mit obiger Methode aufrufe.

    Rufe ich z.B. einen Shell-Befehlt auf (Pfad: @"/bin/ls") klappt alles wunderbar. Auch NSLog geht weiterhin.

    Versuch ich aber einen eigenen Shellscript aufzurufen (Pfad: @"~/Scripts/test.sh) wird das Script zwar ausgeführt, NSLog ist aber danach kaputt. Dabei sieht man Shellscript wie folgt aus:

    Shell-Script

    1. #!/bin/bash
    2. echo Hello
    3. exit 0


    Hat jemand vielleicht einen Tipp an was das liegen könnte? Ich bin mit meinem kleinen Cocoa-Latein leider am Ende.... Ob exit fehlt oder dran ist, scheint keinen Unterschied zu machen...
  • Habe das Problem nun weiter eingrenzen können. Es liegt nicht daran, dass ich setStandardError bei NSTask benutze. Es liegt am aufgerufenen Shellscript, der die Konsole von Xcode verbläst! Bash geht nicht, tcsh klappt.

    Dies hier geht:

    Quellcode

    1. #!/bin/tcsh
    2. echo Hello


    dies geht nicht:

    CODE]#!/bin/bash
    echo Hello
    [/CODE]

    Wobei "es geht" heißt: Shellscript wird ausgeführt UND NSLog bleibt in Takt.
  • Ich erdreiste mich mal, diesen alten Thread wieder nach oben zu holen. Ich kann das Problem nur bestätigen. bash per NSTask starten -> NSLog in XCode kaputt.

    Das ist sehr Ärgerlich, da ich das brauche um den Pfad eines Programmes (über which) zuverlässig rauszufinden. Wenn da noch jemand eine Idee hat, wäre das toll (kann man vielleicht xcode auf eine andere Shell umbiegen?). Ansonsten werde ich das wohl mal als Bug an Apple melden.