Synchronous NSTask?
Synchronous NSTask?
- Subject: Synchronous NSTask?
- From: Randall Meadows <email@hidden>
- Date: Fri, 2 Apr 2004 17:07:01 -0500
Not really synchronize NSTask, but I need to "synchronize" what I run
inside it...
I need to maintain a two-way conversation with a shell process:
define variables, navigate a directory hierarchy, invoke
command-line tools with arguments on items found in the current
directory, etc. Basically, a Terminal session done programmatically.
What I do is:
1) Construct an NSTask object;
2) assign pipes to stdIn and stdOut and stdErr;
3) launch a shell (currently /bin/sh) (this is the "task");
At this point I need to carry on a synchronous, interactive
"conversation" with a shell task. I issue a command (just as I would
at the Terminal prompt, like 'cd whatever') via the -write: method
for the NSFileHandle that I installed as the standardInput for the
task; I have a DataAvailable observer installed to watch for the
result of the command. Since I need to wait for that command to
finish before issuing another one, I use the notification method to
set an instance variable, and then I essentially block waiting for
that instance variable to be set, then read the data using
-availableData:. Problem: the notification method is never hit.
Forcing -availableData: to be called results in it indefinitely
blocking.
Here's some code:
Setting up the task:
-----
readHdl = [[NSPipe pipe] fileHandleForReading];
writeHdl = [[NSPipe pipe] fileHandleForWriting];
task = [[[NSTask alloc] init] autorelease];
[task setStandardInput:writeHdl];
[task setStandardOutput:readHdl];
[task setStandardError:readHdl];
[task setLaunchPath:@"/bin/sh"];
-----
Here's how I issue the command to the shell:
-----
- (NSString *)executeShellCommand:(NSString *)command
{
NSData *data;
NSMutableString *result = [NSMutableString string], *temp;
NSFileHandle *fileHdl;
NSString *cmd;
cmd = ([command hasSuffix:@"\n"]) ? command : [command
stringByAppendingString:@"\n"];
// Register to get notified when data is available
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(shellDataAvailable:)
name:NSFileHandleDataAvailableNotification object:nil];
dataAvailable = NO;
// Write the command to the shell
fileHdl = [task standardInput];
[fileHdl write
Data:[cmd dataUsingEncoding:NSASCIIStringEncoding]];
// Read all the output from it
fileHdl = [task standardOutput];
[fileHdl waitForDataInBackgroundAndNotify];
while (!dataAvailable) {
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.3]];
}
data = [fileHdl availableData];
[temp initWith
Data:data encoding:NSASCIIStringEncoding];
[result appendString:temp];
[temp release];
[[NSNotificationCenter defaultCenter] removeObserver:self];
return(result);
}
-----
The notification callback:
-----
- (void)shellDataAvailable:(NSNotification *)notification
{
dataAvailable = YES;
}
-----
If it matters, all this code is within a thread.
--
randy <
http://www.not-pc.com/>
I think switching to an all-vegetarian diet only makes sense. Not for
health reasons, mind you, but for convenience, since most vegetarians
are weaker and easier to catch. --Charles Gulledge
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.