我的问题是我有一个孩子.app
,我想在注入一些参数后运行它。想要做的是将应用程序作为父应用程序运行(启动它同步并将焦点/激活事件传播到子应用程序)。
我的目标是创建一个启动另一个应用程序的“父应用程序”,例如OtherApp.app
. 它应该看起来好像“父应用程序”是 OtherApp.app
(即不在扩展坞中显示为单独的应用程序,但窗口OtherApp.app
应该包含在“父应用程序”中)。我想这样做的原因是我可以在OtherApp.app
不修改.app
自身的情况下传递一些初始化变量。
我采取的方法
第一种方法是最简单的。只需使用
system(@"VAR=VALUE /Applications/OtherApp.app")
. 然而,这样做的问题是“父应用程序”将立即退出并OtherApp.app
在 Dock 中作为单独的应用程序打开。第二种方法:我尝试过使用
NSWorkspace
withNSRunningApplication
但是它不是同步的,问题是“父应用程序”将再次立即死亡:#import <Cocoa/Cocoa.h> int main(int argc, const char * argv[]) { NSRunningApplication* childApp = [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:@"/Applications/OtherApp.app"] options:NSWorkspaceLaunchDefault|NSWorkspaceLaunchWithoutAddingToRecents configuration:@{ NSWorkspaceLaunchConfigurationEnvironment: @{ @"VAR": @"VALUE" } } error:NULL]; }
第三种方法是使用启动服务。然而,这就是我的问题所在——我找不到任何不推荐使用的 API 可以让我传递环境变量或“启动服务密钥”(例如 LSUIElement),也找不到让我传递环境变量的方法。这也立即退出(我不熟悉 Launch Services 的内部结构,也许有人可以启发我?)
#import <Cocoa/Cocoa.h> int main(int argc, const char * argv[]) { LSLaunchURLSpec launchSpec; launchSpec.appURL = CFBridgingRetain([NSURL fileURLWithPath:@"/Applications/OtherApp.app"]); launchSpec.asyncRefCon = NULL; launchSpec.launchFlags = kLSLaunchDefaults; launchSpec.passThruParams = NULL; // Where can I specify environment vars or args? return LSOpenFromURLSpec(&launchSpec, NULL); }
可能的解决方案
- 创建一个
NSApplication
与之通信的OtherApp.app
“父应用程序”不会立即退出。这里的问题是,现在它们是 Dock 中的两个应用程序,而且保持焦点同步似乎是一项更复杂的任务。 - 弄清楚如何将环境变量传递给
LS
(启动服务)API,并以某种方式控制生成的应用程序的焦点。 - 以某种方式访问捆绑包并动态加载虽然我通常不能与可执行文件一起使用
NSApplicationMain
(它会抛出一个错误)。OtherApp.app
NSBundle
现在,#2 感觉是最好的选择,尽管我们将不胜感激对替代解决方案的任何帮助。