在 Mac 应用程序中嵌入可执行文件
Posted
技术标签:
【中文标题】在 Mac 应用程序中嵌入可执行文件【英文标题】:Embed Executable inside Mac Application 【发布时间】:2012-08-17 20:31:13 【问题描述】:如果您访问/usr/bin
,您将看到数百个可执行文件或可执行文件的链接。
我的应用程序(在 Xcode 中用 Obj-C 编写的 Mac 应用程序)依赖于其中一些可执行文件。不幸的是,必须手动安装可执行文件 - 我必须检查它们,然后提示用户安装它们。
我的代码是:
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/usr/bin/executable"];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[task setArguments:[NSArray arrayWithObjects:sender, target, nil]];
[task launch];
我想知道是否可以将我的应用程序中的可执行文件复制到某个地方,然后从那里调用它。这样,用户就不必自己去获取它。
Mac App Store 会允许吗?
【问题讨论】:
一般来说,只需在构建时将它们作为应用程序包的一部分就可以了。不幸的是,我对问题的应用商店部分一无所知。 @Lvsti 你到底是什么意思?如,我应该在哪里添加可执行文件?我将如何“在构建时使它们成为应用程序包的一部分”?我该怎么称呼它 -setPathLaunch
是什么?
我怀疑应用商店不允许允许此类恶作剧,因为沙盒可能不允许启动外部任务。 Other people have been thinking about this question as well.
【参考方案1】:
如果您想知道,在 Swift 3 中您可以这样做:
let bundle = Bundle.main
let task = Process()
let path = bundle.path(forResource: "executableName", ofType: "")
task.launchPath = path
【讨论】:
【参考方案2】:只是为了更新和澄清,我发现以下内容适用于 Xcode 11 和 Swift 5。
首先,将所需的可执行文件(在我的例子中是 pandoc)拖放到我的 Xcode 项目中。我把它放在一个名为“bin”的组/文件夹中。
确保选择我希望包含可执行文件的目标!
然后使用以下代码:
let task = Process()
let bundle = Bundle.main
let execURL = bundle.url(forResource: "pandoc", withExtension: nil)
guard execURL != nil else
print("Pandoc executable could not be found!")
return
task.executableURL = execURL!
task.arguments = ["--version"]
do
try task.run()
print("Pandoc executed successfully!")
catch
print("Error running Pandoc: \(error)")
【讨论】:
【参考方案3】:好的,所以我开始尝试自己寻找答案。而且,我很高兴地说我想通了!
因此,只需将executable
复制到 Xcode 项目中您想要的任何位置。然后,改变
[task setLaunchPath:@"/usr/bin/executable"];
到
[task setLaunchPath:[[NSBundle mainBundle] pathForResource:@"executable" ofType:@""]];
还有哒哒!
【讨论】:
感谢您的回答。请问您可以使用这种方法通过 App Store 分发吗?【参考方案4】:在 Swift 中,您可以这样做:
let bundle = NSbundle.mainBundle()
let task = NSTask()
task.launchPath = bundle.pathForResource("executableName", ofType: "")
确保捆绑的可执行文件位于目录树的顶层,而不是像 /lib 这样的子目录,否则它可能无法工作。
【讨论】:
【参考方案5】:我更新了 hbowie 的答案,将从 shell 接收到的值作为字符串返回:
func safeShell(_ strExecutable:String, _ arrArguments:Array<String>) throws -> String
let task = Process()
let pipe = Pipe()
let bundle = Bundle.main
let execURL = bundle.url(forResource: strExecutable, withExtension: nil)
//no point in going on if we can't find the program
guard execURL != nil else
print("\(strExecutable) executable could not be found!")
return ""
task.executableURL = execURL!
task.arguments = arrArguments
task.standardOutput = pipe
task.standardError = pipe
//task.arguments = ["-c", command]
//task.executableURL = URL(fileURLWithPath: "/bin/zsh") //<--updated
do
try task.run() //<--updated
catch throw error
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)!
return output
使用示例:
let strOutput = try myAppManager.safeShell("pandoc", ["--version"])
print(strOutput)
返回:
pandoc 2.16.2
Compiled with pandoc-types 1.22.1, texmath 0.12.3.2, skylighting 0.12.1,
citeproc 0.6, ipynb 0.1.0.2
User data directory: /Users/stevesuranie/Library/Containers/MartianTribe.MD2html/Data/.local/share/pandoc
Copyright (C) 2006-2021 John MacFarlane. Web: https://pandoc.org
This is free software; see the source for copying conditions. There is no
warranty, not even for merchantability or fitness for a particular purpose.
【讨论】:
以上是关于在 Mac 应用程序中嵌入可执行文件的主要内容,如果未能解决你的问题,请参考以下文章