Domanda
Sto cercando di utilizzare NSTask per eseguire il comando UNIX 'apropos'. Ecco il mio codice:
NSTask *apropos = [[NSTask alloc] init];
NSPipe *pipe = [[NSPipe alloc] init];
[apropos setLaunchPath:@"/usr/bin/apropos"];
[apropos setArguments:[NSArray arrayWithObjects:@"filename", @"match", nil]];
[apropos setStandardOutput:pipe];
[apropos launch];
[apropos waitUntilExit];
Il problema è che questo non ritorna mai. Ho anche provato ad utilizzare codice di esempio di Apple (TaskWrapper) e restituisce l'output (in tre segmenti), ma non è mai chiama il gestore processFinished.
Inoltre, l'appendOutput: gestore riceve i duplicati. Così, per esempio, se i rendimenti apropos questo:
1 2 3 4 5
Potrei ricevere qualcosa di simile:
1 2 3
1 2 3 4
5
(raggruppati in 3 messaggi di aggiunta).
rilevo che Apropos visualizza l'output in un formato in cui è possibile scorrere su e giù nella linea di comando invece di emettere direttamente i dati direttamente nell'output standard; Come faccio a leggere questo modo affidabile attraverso NSTask e NSPipe?
Soluzione
Ho appena testato questo programma e funziona bene:. I termina programma e /tmp/apropos.txt
contiene l'output del apropos
#import <Foundation/Foundation.h>
int main()
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSTask *apropos = [[[NSTask alloc] init] autorelease];
NSPipe *pipe = [[[NSPipe alloc] init] autorelease];
NSFileHandle *readHandle = [pipe fileHandleForReading];
[apropos setLaunchPath:@"/usr/bin/apropos"];
[apropos setArguments:[NSArray arrayWithObjects:@"filename", @"match", nil]];
[apropos setStandardOutput:pipe];
[apropos launch];
[apropos waitUntilExit];
NSString *output = [[[NSString alloc]
initWithData:[readHandle readDataToEndOfFile]
encoding:NSUTF8StringEncoding] autorelease];
[output writeToFile:@"/tmp/apropos.txt" atomically:YES
encoding:NSUTF8StringEncoding error:NULL];
[pool drain];
return 0;
}
Sei per caso utilizzando NSLog()
per ispezionare l'uscita? Se è così, potrebbe essere necessario impostare un tubo per stdin
come spiegato in questa risposta di miniera per un NSTask correlata domanda . Sembra che NSLog()
invio dei dati al stderr
colpisce NSTask
.
Altri suggerimenti
Con il codice originale, immagino che sia perché non state leggendo l'output del comando. I tubi hanno solo una dimensione di buffer limitato, e se non avete letto l'uscita del compito, si può finire in attesa appeso per il buffer a svuotarsi. Io non so nulla circa il codice di esempio si è tentato così io non ci posso fare a meno. Per quanto riguarda l'ultima domanda, apropos
utilizza solo il cercapersone quando è collegato ad un terminale. Non stai emulando un terminale, in modo che non ci si deve preoccupare. È possibile dimostrare questo eseguendo apropos whatever | cat
nel terminale e verificare che il cercapersone non viene richiamato.