【问题标题】:Run user defined command with NSTask使用 NSTask 运行用户定义的命令
【发布时间】:2012-09-05 16:36:05
【问题描述】:

我想执行用户指定的终端命令。例如,用户可能在文本字段中写入killall "TextEdit"say "Hello world!",而我想执行该命令。

NSTask 是要走的路,除了我有两个问题:

第一:参数。现在我正在这样做:

NSArray* args = [commandString componentsSeparatedByString: @" "];
[task setArguments: [args subarrayWithRange: NSMakeRange(1, [args count] - 1)]]; // First one is the command name

这是这样做的方法吗?我不认为我对此有任何问题,但我看起来并不安全。想象一下:用户写了killall 'Address Book',但命令接收'AddressBook'??那是行不通的。那么,我应该怎么做呢?如何安全地解析参数?

第二:启动路径。只需要编写命令的名称而不是完整的路径对用户来说更加友好。所以我想支持这一点,这意味着以编程方式找出只有它的名称的命令的完整路径。为此,我在 NSTask 上写了一个这样的类别:

+ (NSString*)completePathForExec: (NSString*)exec
{
    NSTask* task = [[NSTask alloc] init];
    NSPipe* pipe = [[NSPipe alloc] init];

    NSArray* args = [NSArray arrayWithObject: exec];
    [task setLaunchPath: @"/usr/bin/which"];
    [task setArguments: args];
    [task setStandardOutput: pipe];
    [task setStandardError: pipe];

    [task launch];    
    [task waitUntilExit];

    NSFileHandle* file = [pipe fileHandleForReading];
    NSString* result = [[NSString alloc] initWithData: [file readDataToEndOfFile] encoding: NSASCIIStringEncoding];

    if ([result length]) {
        if ([result hasSuffix: @"\n"]) { result = [result substringWithRange: NSMakeRange(0, [result length] - 1)]; }

        return result;
    }
    else { return exec; }
}

这似乎运作良好。但是,我如何确定这条路径:/usr/bin/which 将始终有效?我的意思是:它会在 10.6、10.7、10.8 等上运行吗?我想我曾经遇到过一个问题,即 shell 命令的路径随系统版本而变化,你永远不会太小心。

如果保证路径保持不变,那么这不是问题。如果它改变了,那我怎么知道'路径查找器的路径'?

【问题讨论】:

    标签: objective-c cocoa nstask


    【解决方案1】:

    不用重新发明命令行解析轮对您来说会容易得多。但是,当然,执行任意用户输入的代码是一场安全噩梦(由于用户可以访问系统,因此可能直接运行终端)。

    具体来说,让 NSTask 使用命令行选项包装其中一个 shell 的调用,以使其执行任意字符串。

    sh -c "ls -alF"
    

    这将允许您将路径传递给sh 作为您的启动路径,该路径位于每个系统的固定位置。 @"-c" 参数告诉sh 将下一个参数解析为脚本,当然,下一个参数是用户输入的任何内容。

    请注意,这也将赋予用户管道传输的能力。

    【讨论】:

    • 太棒了!比我预期的要简单得多。但是我确实有一个问题:我应该使用什么字符来关闭用户输入的命令,使它变成一个字符串?如果我使用"' 命令可能会被拆分为多个参数,因为用户可能也在使用这些字符。
    • 实际上,我想我已经想通了:使用用户命令创建一个临时文件,创建一个 NSTask 并使用该文件的路径作为参数并运行该任务。最后删除临时文件。
    猜你喜欢
    • 2015-03-26
    • 2011-10-17
    • 2014-07-30
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多