• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Reading return values from NSTask
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Reading return values from NSTask


  • Subject: Re: Reading return values from NSTask
  • From: Shawn Erickson <email@hidden>
  • Date: Sun, 28 Dec 2003 16:02:02 -0800

On Dec 28, 2003, at 2:40 PM, KLW wrote:

Hello,

I'm trying to execute a perl script from within my Cocoa application and get its return value (not its exit status). I've tried two approaches: 1) using a c system() call (which, I believe will only net me an exit status), or 2) using NSTask, like so:

<ugly code>
NSString * argument = [[NSString alloc] initWithCString: argv[1]];
NSTask *task = [[NSTask alloc] init];
NSFileHandle *readHandle = [[NSFileHandle alloc] init];
NSData *inData = [[NSData alloc] init];
NSMutableString *outString = [[NSMutableString alloc] init];
NSMutableArray *args = [NSMutableArray array];
NSLog(@"Passing: %@",argument);
[args addObject:argument];
[task setStandardOutput:readHandle];
[task setLaunchPath:@"/path/to/my/perl/script.pl"];
[task setArguments:args];
[task launch];
</ugly code>

So far so good. The task launches correctly, and the console gets the correct output from the perl script. However, when I try to read the output to Cocoa, I run into trouble. I can't figure out (having looked at the NSTask page about thirty times) how to read ordinary output back into a variable. My attempt is here:
<really ugly code>
if ((inData = [readHandle availableData]) && [inData length]) {
outString = [outString initWithData:inData encoding:NSASCIIStringEncoding];
// outString = [inData description];
}
[task terminate];
NSString *result = [[NSString alloc] initWithFormat: @"result: %@",outString];
NSLog(result);

</really ugly code>

Do you wait for the task to complete before trying to read in data? You code sample doesn't show that.

I do notice some strange things in your code snippet above... You allocate and init inData and outString at the beginning yet replace them later on in you code without releasing what you inited. You appear to believe that you have to allocate those before that can be assigned to... you don't. I suggest reading up on Objective-C a little more to better understand the difference between objects and references to objects. Also it is cleaner to use NSArray's arrayWithObject or arrayWithObjects then creating a NSMutableArray to later simply add a single item to it that you had on hand when you created the array in the first place. Finally you need not call terminate on the task, it will exist when it is done running (assuming the script you are running exists).

Anyway this is one example of how I use NSTask in a project of mine...

- (void)initSwapFileRootDirectory
{
NSData* data;

NSTask* ls = [[[NSTask alloc] init] autorelease];
[ls setStandardOutput:[NSPipe pipe]];
[ls setLaunchPath:@"/bin/sh"];
[ls setArguments:[NSArray arrayWithObjects:...]];
[ls launch];
[ls waitUntilExit];

data = [[[ls standardOutput] fileHandleForReading] availableData];
if ((data != nil) && [data length]) {
NSString* tmpString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
...
}
}

Or done another way...

...
eater = [[NSTask alloc] init];
[eater setStandardOutput:[NSPipe pipe]];
[eater setLaunchPath:eaterPath];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(eaterTerminated:)
name:NSTaskDidTerminateNotification
object:nil];

NSFileHandle* outFileHandle = [[eater standardOutput] fileHandleForReading];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(readFromStandardOutput:)
name:NSFileHandleDataAvailableNotification
object:outFileHandle];
[outFileHandle waitForDataInBackgroundAndNotify];
[eater launch];
...

- (void)readFromStandardOutput:(NSNotification*)aNotification
{
NSString *bytes;
NSData *data;

if (eater == nil) return;
if ((data = [[aNotification object] availableData]) == nil) return;

bytes = [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
[textField setStringValue:[NSString stringWithFormat: @"Memory Eater PID:%d - Eaten: %ld (MB)",
[eater processIdentifier],
[bytes intValue] / (1024*1024)]];

[[[eater standardOutput] fileHandleForReading] waitForDataInBackgroundAndNotify];
}

-Shawn
_______________________________________________
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.

  • Follow-Ups:
    • Re: Reading return values from NSTask
      • From: KLW <email@hidden>
References: 
 >genstrings not working (From: David Kocher <email@hidden>)
 >Re: genstrings not working (From: "Louis C. Sacha" <email@hidden>)
 >Reading return values from NSTask (From: KLW <email@hidden>)

  • Prev by Date: Re: Making a delegate NSResponder
  • Next by Date: Re: Making a delegate NSResponder
  • Previous by thread: Re: Reading return values from NSTask
  • Next by thread: Re: Reading return values from NSTask
  • Index(es):
    • Date
    • Thread