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