NSTask Does Not Terminate
I'm trying to use NSTask to run the UNIX 'apropos' command. Here's my code:
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];
The problem is that this never returns. I also tried using Apple's example code (TaskWrapper) and it returns the output (in three segments) but it never calls the processFinished handler.
Furthermore, the appendOutput: handler receives duplicates. So, for example, if apropos returns this:
1 2 3 4 5
I might receive something like this:
1 2 3
1 2 3 4
5
(grouped into 3 append messages).
I note that Apropos displays the output in a format where it's possible to scroll up and down in the command line instead of just directly outputting the data straight to standard output; how do I read this reliably through NSTask and NSPipe?
I’ve just tested this program and it works fine: the program terminates and /tmp/apropos.txt
contains the output of 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;
}
Are you by any chance using NSLog()
to inspect the output? If so, you might need to set a pipe for stdin
as explained in this answer of mine to an NSTask related question. It seems that NSLog()
sending data to stderr
affects NSTask
.
With your original code, I would imagine it's because you're not reading the output of the command. The pipes only have a limited buffer size, and if you don't read the output of the task, it can end up hung waiting for the buffer to empty out. I don't know anything about the sample code you tried so I can't help there. As for the last question, apropos
only uses the pager when it's connected to a terminal. You're not emulating a terminal, so you don't have to worry. You can prove this by running apropos whatever | cat
in the terminal and verifying that the pager is not invoked.
精彩评论