Running/launching an existing executable program from swift on macOS

Hi All, O.K. I'm new to swift and apple. I've worked in C and Tcl/Tk. What I'm trying to do is run an executable on MacOS from swift. Specifically aescrypt. I've played with Process and task.esecutableURL but they all seem to fail. Any hints. Thanks

I'm guessing you tried to use the path to your executable for executableURL, while it should be the path to the shell.

Something like this works for me:

import Foundation

let process = Process()
let pipe = Pipe()

process.standardOutput = pipe // you can also set stderr and stdin
process.executableURL = URL(fileURLWithPath: "/bin/bash") // or any other shell you like
process.arguments = ["-c", "the command you use to run your executable normally"]

try! process.run()
//	process.waitUntilExit() // you might need this

let data = pipe.fileHandleForReading.readDataToEndOfFile()

guard let standardOutput = String(data: data, encoding: .utf8) else {
	FileHandle.standardError.write(Data("Error in reading standard output data".utf8))
	fatalError() // or exit(EXIT_FAILURE) and equivalent
	// or, you might want to handle it in some other way instead of a crash
}

In addition, you can wrap the whole thing in a function like this:

/// Executes a shell command with `/bin/bash`.
/// - Parameter command: The command to execute.
/// - Returns: The standard output from executing `command`.
@discardableResult
func bash(_ command: String) -> String { ... }

and then call it like this:

bash("the command you use to run your executable normally")
// or
let standardOutput = bash("the command you use to run your executable normally")
1 Like

Thank you. I now have it working for what I wanted, and your explanation was the key !

// Thanks again wow bagger, you example/suggestion brought me to this code below.
// This is what worked for me to run command aescrypt. put together from several sources
// below now works**

import Foundation

func executeCommand(command: String, args: [String]) -> String {
let task = Process()
task.launchPath = command
task.arguments = args
let pipe = Pipe()

task.standardOutput = pipe
task.launch()

let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output: String = String(decoding: data, as: UTF8.self)
return output
}
let commandOutput = executeCommand(command:"/bin/bash",args: ["-c", "exec /usr/local/bin/aescrypt -k /Users/usr/.secret.key -e /Users/usr/test.swift"])**

I have a problem with an executable that asks for permissions ; when I execute it from terminal, the 1st time a window is open and I can script the requested permission, and from then it works regularly ; while, launching in this way, the window is not open, and even if I had previously granted permission via terminal, it gives error anyway (is there a way to request additional privileges when execute shell?)

Make sure you are reading the output buffers (standard and errors), else your program call might crash or hang after too much unread output. You might have a look at this function.