简体   繁体   English

当从 xcode 运行时,使用 NSTask 的 Swift 2.1 OSx shell 命令工作,但在导出时不起作用

[英]Swift 2.1 OSx shell commands using NSTask work when run from xcode, but not when exported

I wrote a simple OSx (10.11) application to execute shell commands when a button is pressed.我编写了一个简单的 OSx (10.11) 应用程序来在按下按钮时执行 shell 命令。 It works when I run it from xcode, but when I export the application via "archive", one of the buttons no longer works.当我从 xcode 运行它时它可以工作,但是当我通过“归档”导出应用程序时,其中一个按钮不再起作用。 I don't get an error and I don't get any output either.我没有收到错误,也没有得到任何输出。 I am using absolute paths so I don't understand why it works in xcode but not as an exported application, Nor do I understand why one button works and the other doesn't.我使用的是绝对路径,所以我不明白为什么它在 xcode 中有效,但不能作为导出的应用程序,我也不明白为什么一个按钮有效而另一个无效。

Here is the main function that I am using the make the shell commands这是我使用 make shell 命令的主要功能

    func runCommand(path : String, args : [String]) -> (output: [String], error: [String], exitCode: Int32) {
    var output : [String] = []
    var error : [String] = []

    let task = NSTask()
    task.launchPath = path
    task.arguments = args

    let outpipe = NSPipe()
    task.standardOutput = outpipe
    let errpipe = NSPipe()
    task.standardError = errpipe

    task.launch()

    let outdata = outpipe.fileHandleForReading.readDataToEndOfFile()
    if var string = String.fromCString(UnsafePointer(outdata.bytes)) {
        string = string.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
        output = string.componentsSeparatedByString("\n")
    }

    let errdata = errpipe.fileHandleForReading.readDataToEndOfFile()
    if var string = String.fromCString(UnsafePointer(errdata.bytes)) {
        string = string.stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
        error = string.componentsSeparatedByString("\n")
    }

    //task.waitUntilExit()
    let status = task.terminationStatus

    return (output, error, status)
}

and here is the button that works:这是有效的按钮:

      // Check for configurator 2 app installation
    let (output, error, status) = self.runCommand("/bin/bash", args:  ["-c", "/bin/ls", "/Applications/Apple Configurator 2.app"])

and here is the button that doesn't:这是没有的按钮:

        // Check if the phone is plugged in and paired
    let (output, error, status) = self.runCommand("/bin/bash", args: ["-c", "/usr/local/bin/cfgutil", "get", "isPaired"])

What is even more strange, I discovered (through sheer frustration) that if I repeatedly click the button that doesn't work, it will sometimes eventually work.更奇怪的是,我发现(完全出于沮丧)如果我反复单击不起作用的按钮,它有时最终会起作用。

Your issue is the result of two things happening together:您的问题是两件事情同时发生的结果:

  • you return default values你返回默认值

  • you don't specify alternative branches for the control flow您没有为控制流指定替代分支

What happens is that it hides potential failures, and leads to code that is very hard to debug, as you experienced.发生的情况是它隐藏了潜在的故障,并导致代码很难调试,正如您所经历的那样。

A possible solution with your existing code is to cover all possible ways, meaning providing else branches to your if var string = String.fromCString(UnsafePointer(errdata.bytes)) conditions, where you will handle errors.您现有代码的一个可能解决方案是涵盖所有可能的方式,这意味着为您的if var string = String.fromCString(UnsafePointer(errdata.bytes))条件提供else分支,您将在其中处理错误。

Thanks to Eric D. I simplified my code and now everything is working.感谢 Eric D。我简化了代码,现在一切正常。

func runCommand(path : String, args : [String]) -> (output: NSString, error: NSString, exitCode: Int32) {
    let task = NSTask()
    task.launchPath = path
    task.arguments = args

    let outpipe = NSPipe()
    task.standardOutput = outpipe
    let errpipe = NSPipe()
    task.standardError = errpipe

    task.launch()

    let outdata = outpipe.fileHandleForReading.readDataToEndOfFile()
    let output = NSString(data: outdata, encoding:  NSUTF8StringEncoding)

    let errdata = errpipe.fileHandleForReading.readDataToEndOfFile()
    let error_output = NSString(data: errdata, encoding: NSUTF8StringEncoding)

    task.waitUntilExit()
    let status = task.terminationStatus

    return (output!, error_output!, status)
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 NSTask在xcode运行中工作,但当我在xcode外部运行时无法运行 - NSTask works in xcode run but not when i run it outside xcode 在Xcode中使用NSTask在AppKit应用程序中运行时,Rust 1.4.0(或更高版本)货物/铁锈崩溃 - Rust 1.4.0 (or later) cargo/rustc crashes when run in an AppKit app using NSTask in Xcode dyld:尝试使用NSTask从Objective-C运行Fortran可执行文件时未加载库 - dyld: Library not loaded when trying to run Fortran executable from Objective-C using NSTask 从Xcode shell脚本运行时缺少Ruby gem - Ruby gems missing when run from Xcode shell script 为什么从 Swift (Xcode) 调用时 fstream 不起作用? - Why doesn't fstream work when called from Swift (Xcode)? 使用cmake生成xcode项目时为什么CMAKE_OSX_DEPLOYMENT_TARGET不起作用? - Why the CMAKE_OSX_DEPLOYMENT_TARGET not work when using cmake generate xcode project? Swift脚本直接在Xcode Run Script阶段工作,但由于NSTask / Process而不能通过外部文件 - Swift script works directly inside Xcode Run Script phase, but not via external file due to NSTask/Process 当我在 Xcode 中运行 Product -> Archive 时会执行哪些 `xcodebuild` 命令? - What `xcodebuild` commands are executed when I run Product -> Archive in Xcode? Xcode Cocoa目标C使用NSTask执行“查找” Shell命令返回语法 - Xcode Cocoa Objective C Using NSTask to Execute “Find” Shell Command Returns Syntax 使用xcode 6.1(OSX)在Swift中解决NSTextField的问题 - Trouble with NSTextField in Swift using xcode 6.1 (OSX)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM