本文介绍了如何使用多个命令运行NSTask的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使NSTask运行如下命令:

I'm trying to make a NSTask running a command like this:

这是我的方法

- (void) processByName:(NSString*)name {
    NSTask *task1 = [[NSTask alloc] init];
    NSPipe *pipe1 = [NSPipe pipe];
    [task1 waitUntilExit];
    [task1 setLaunchPath: @"/bin/ps"];
    [task1 setArguments: [NSArray arrayWithObjects: @"-clx", nil]];
    [task1 setStandardOutput: pipe1];

    NSTask *task2 = [[NSTask alloc] init];
    NSPipe *pipe2 = [NSPipe pipe];
    [task2 setLaunchPath: @"/usr/bin/grep"];
    [task2 setArguments: [NSArray arrayWithObjects: @"'Finder'", nil]];
    [task2 setStandardInput:pipe1];
    [task2 setStandardOutput: pipe2];

    NSTask *task3 = [[NSTask alloc] init];
    NSPipe *pipe3 = [NSPipe pipe];
    [task3 setLaunchPath: @"/usr/bin/grep"];
    [task3 setArguments: [NSArray arrayWithObjects: @"'{print $2}'", nil]];
    [task3 setStandardInput:pipe2];
    [task3 setStandardOutput: pipe3];

    NSFileHandle *file = [pipe3 fileHandleForReading];

    [task1 launch];
    [task2 launch];
    [task3 launch];

    NSData *data;
    data = [file readDataToEndOfFile];

    NSString *string;
    string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];

    NSLog(@"Result: %@", string);
}

但是结果仅仅是

我在做什么错了?

编辑

- (void) processByName:(NSString*)name {
    NSTask *task1 = [[NSTask alloc] init];
    NSPipe *pipe1 = [NSPipe pipe];
    [task1 waitUntilExit];
    [task1 setLaunchPath: @"/bin/ps"];
    [task1 setArguments: [NSArray arrayWithObjects: @"-clx", nil]];
    [task1 setStandardOutput: pipe1];

    NSTask *task2 = [[NSTask alloc] init];
    NSPipe *pipe2 = [NSPipe pipe];
    [task2 setLaunchPath: @"/usr/bin/grep"];
    [task2 setArguments: [NSArray arrayWithObjects: @"'Finder'", nil]];
    [task2 setStandardInput:pipe1];
    [task2 setStandardOutput: pipe2];

    NSTask *task3 = [[NSTask alloc] init];
    NSPipe *pipe3 = [NSPipe pipe];
    [task3 setLaunchPath: @"/usr/bin/grep"];
    [task3 setArguments: [NSArray arrayWithObjects: @"'{print $2}'", nil]];
    [task3 setStandardInput:pipe2];
    [task3 setStandardOutput: pipe3];

    NSFileHandle *file = [pipe3 fileHandleForReading];

    [task1 launch];
    [task2 launch];
    [task3 launch];

    [[NSNotificationCenter defaultCenter] addObserverForName:NSTaskDidTerminateNotification
                                                      object:task3
                                                       queue:nil
                                                  usingBlock:^(NSNotification* notification){

                                                      NSData * data = [file readDataToEndOfFile];

                                                      NSString * string;
                                                      string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
                                                      NSLog(@"Result: %@", string);
                                                  }];
}

推荐答案

任务在与代码不同的进程中运行,即异步运行.到稍后两行到达readDataToEndOfFile时,它们可能还没有完成(甚至可能还没有启动!).

The tasks run in a separate process from your code, i.e., asychronously. They probably haven't finished (they may not have even launched!) by the time you get to the readDataToEndOfFile two lines later.

如果您已经在后台线程中,则可以轮询其状态:while( ![task isRunning]){,或者如果您在主线程中,建议使用GCD将其放入队列并进行轮询在那里.

If you're already on a background thread here, you can poll their status: while( ![task isRunning]){, or if you're on the main thread, I'd suggest using GCD to put this onto a queue and doing the polling there.

实际上,比使用通知更好:

Actually, better than that would be to use notifications:

[task3 launch];

[[NSNotificationCenter defaultCenter] addObserverForName:NSTaskDidTerminateNotification
                                                  object:task3
                                                   queue:nil
                                              usingBlock:^{

    NSData * data = [file readDataToEndOfFile];

    NSString * string;
    string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];

    NSLog(@"Result: %@", string);
}];

请参见 TN2050:无需轮询即可观察过程寿命..每个NSTask终止时都会发送NSTaskDidTerminateNotification(理想情况下,您应该检查其返回代码,而不是假设其已成功运行).您可以创建一个块,以在task3发送该通知时运行.

See TN2050: Observing Process Lifetime Without Polling. Each NSTask will send NSTaskDidTerminateNotification when it terminates (you should, ideally, check its return code rather than assuming it ran successfully). You can create a block to be run when task3 sends that notification.

这篇关于如何使用多个命令运行NSTask的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-18 14:55