objective-c - 具有多个管道输入的 NSTask

标签 objective-c cocoa nstask nspipe

我正在尝试使用管道来处理需要多个输入的命令,但不太确定该怎么做。这是我正在尝试做的事情的片段。我知道如何处理第一个输入,但我不知道如何处理第二个输入的管道 -newstdinpass

NSTask *task = [[NSTask alloc] init];
NSPipe *pipe = [NSPipe pipe];

[task setLaunchPath: @"/bin/sh"];
[task setArguments: [NSArray arrayWithObjects: @"-c", @"/usr/bin/hdiutil chpass -oldstdinpass -newstdinpass /path/to/dmg", nil]];
[task setStandardInput:pipe];
[task launch];

[[pipe fileHandleForWriting] writeData:[@"thepassword" dataUsingEncoding:NSUTF8StringEncoding]];
[[pipe fileHandleForWriting] closeFile];

[task waitUntilExit];
[task release];

所以我知道以这种方式使用 hdiutil 有点不对劲,但就管道而言,我的做法是否正确?

谢谢。

更新:为了防止其他人对此感到疑惑,我的问题的一个快速解决方案是传入一个以 null 结尾的字符串,正如 Ken Thomases 在下面指出的那样。使用 [[NSString stringWithFormat:@"oldpass\0newpass\0"] dataUsingEncoding:NSUTF8StringEncoding] 进入管道。现在,还需要学习如何用管道桥接多个 NSTasks...

最佳答案

您可以创建多个 NSTask 和一堆 NSPipe 并将它们连接在一起,或者您可以使用 sh -c 技巧向 shell 提供命令,让它解析并设置所有 IPC。

示例:

NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/sh"];

NSArray *arguments;
arguments = [NSArray arrayWithObjects: @"-c",
                     @"cat /usr/share/dict/words | grep -i ham | rev | tail -5", nil];
[task setArguments: arguments];
// and then do all the other jazz for running an NSTask.

引用: http://borkware.com/quickies/one?topic=nstask


现在,至于“正确的”命令执行函数,这是我通常使用的函数...

代码:

/*******************************************************
 *
 * MAIN ROUTINE
 *
 *******************************************************/

- (void)runCommand:(NSString *)cmd withArgs:(NSArray *)argsArray
{
    //-------------------------------
    // Set up Task
    //-------------------------------

    if (task) { [self terminate]; }

    task = [[NSTask alloc] init];
    [task setLaunchPath:cmd];
    [task setArguments:argsArray];

    [task setStandardOutput:[NSPipe pipe]];
    [task setStandardError:[task standardOutput]];

    //-------------------------------
    // Set up Observers
    //-------------------------------

    [PP_NOTIFIER removeObserver:self];
    [PP_NOTIFIER addObserver:self 
                    selector:@selector(commandSentData:) 
                        name: NSFileHandleReadCompletionNotification 
                      object: [[task standardOutput] fileHandleForReading]];

    [PP_NOTIFIER addObserver:self 
                    selector:@selector(taskTerminated:) 
                        name:NSTaskDidTerminateNotification 
                      object:nil];

    //-------------------------------
    // Launch
    //-------------------------------
    [[[task standardOutput] fileHandleForReading] readInBackgroundAndNotify];

    [task launch];
}

/*******************************************************
 *
 * OBSERVERS
 *
 *******************************************************/

- (void)commandSentData:(NSNotification*)n
{
    NSData* d;
    d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem];

    if ([d length])
    {
        NSString* s = [[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding];

        NSLog(@"Received : %@",s);
    }

    [[n object] readInBackgroundAndNotify]; 
}

- (void)taskTerminated:(NSNotification*)n
{
    [task release];
    task = nil;
}

关于objective-c - 具有多个管道输入的 NSTask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10220928/

相关文章:

iphone - 与另一个 UITableview 同时滚动其他 UITableview

json - Cocoa - 解析 JSON 字符串

cocoa - 剪切 NSScrollView 上的圆角

objective-c - 在 Objective-C 中,有没有简单的方法可以在特殊字符前面添加反斜杠?

iphone - 将变量传递给使用presentViewController加载的 View Controller

iphone - SQLite查询使用SQLite的“like”子句查找相似的单词

cocoa - setFrame 创建的 NSView 在两个维度上都比预期小 15 像素

macos - NSTask 从沙盒应用程序中生成

objective-c - 启动后写入 NSTasks 标准输入

ios - 从 iPhone 浏览 PDF 文件