OSX – 打包一个基于shell的交互式二进制文件

我已经创build了一个小的NodeJS脚本,使用EncloseJS编译,以便应用程序变成它自己的二进制文件。 该应用程序的目的是在terminal运行,并与用户交互。 我想把它打包在一个.app中,所以感觉像一个普通用户可以运行的完整应用程序。

我怎样才能解决这个问题? 到目前为止,我已经尝试了鸭嘴兽的结果混杂,因为它似乎不正确退出。

尝试以下操作:

  • 使用[Apple]Script Editor创build一个新脚本并将其保存为应用程序
  • 将你的二进制文件 – 我们称之为foo – 放在新的.app软件包的Contents/MacOS子文件夹中。
  • 将下面的代码放在应用程序的AppleScript中:
 set embeddedBinary to POSIX path of (path to me) & "Contents/MacOS/foo" tell application "Terminal" do script quoted form of embeddedBinary activate end tell 

当您运行应用程序时,embedded式二进制文件将在您可以与之交互的新的“terminal”窗口中打开。

追加& "; exit" do script命令以自动closuresterminal窗口时,二进制终止。

但是,请注意,您的应用程序仅作为embedded式二进制文件的启动器

  • terminal窗口创build完成后终止
  • 所以它的Dock图标只显示一下,然后再次消失
  • 并且你将不会得到应用程序菜单(无论如何,鉴于你的二进制文件在terminal中运行,这将不是一个选项)。
  • 每次启动应用程序时,即使您的二进制文件已经在运行,也会打开一个新的terminal窗口。

有办法解决这些问题(菜单除外),但他们需要额外的工作 – 见下文。


解决上述问题的解决scheme,以获得更加完整的体验

  • 它保持包装应用程序打开(显示自己的Dock图标)。
  • 它将激活转发到运行embedded式二进制文件的启动terminal窗口,当应用程序被激活时(例如,通过点击Dock图标)
  • 当启动的terminal窗口closures时,包装应用程序自动终止。

但是它有局限性

  • 可悲的是,为了中继激活, 需要GUI脚本 ,这需要在任何给定机器上具有pipe理权限的一次性授权 ; 首次启动时提示用户,但需要几个步骤。
  • 为了使应用程序能够在点击时快速中继激活,并在terminal窗口closures时快速退出,必须频繁地调用它on idle事件处理程序,这会占用CPU资源,尽pipeCPU的额外负载非常小 – 请参阅注释在源代码下面。

说明:

  • 使用[Apple]Script Editor创build一个新脚本并将其保存为保持打开的 应用程序
    • Save为对话框中,select格式Application然后选中Stay open after run handlercheckbox。
  • 将你的二进制文件 – 我们称之为foo – 放在新的.app软件包的Contents/MacOS子文件夹中。
  • 将下面的代码放在应用程序的AppleScript中:
 # Global variable to track the launched Terminal window (tab). global g_winLaunched on run # Get full path of embedded binary. set embeddedBinary to POSIX path of (path to me) & "Contents/MacOS/foo" tell application "Terminal" # Launch embedded binary in new Terminal window, and # have the window closed when the binary terminates *successfully*. # This leaves the window open in case of error - whether on # initial launch or on existing - giving the user a chance to investigate. do script quoted form of embeddedBinary & " && exit" set g_winLaunched to front window end tell end run on idle if frontmost of me then # If this app is activated, relay activation to the launched Terminal window. try # Activate the running window using GUI scripting. # Sadly, `set index of g_winLaunched to 1` is NOT enough to activate the window. # NOTE: This requires that this app be authorized for assistive access via # System Preferences > Security & Privacy > Accessibility. tell application "System Events" perform action "AXRaise" of window (name of g_winLaunched) of process "Terminal" end tell activate application "Terminal" on error tell me to quit # Window is no longer alive, quit this app. end try else # See if tab is still alive, and, if not, quit this app. try id of g_winLaunched on error tell me to quit end try end if # Call this handler every N seconds. # This is a trade-off between responsiveness and CPU usage. # With 0.3 secs., CPU usage of this app is around 0.8% # on my 3.2 Ghz quad-core Intel Core i5 iMac. return 0.3 end idle 

您可以尝试使用一个命令提供Node.JS应用程序的本机打包(自我执行)的JXcore,如:

 $ jx package myapp.js MyApp -native 

然后你可以在OSX(或其他Unix系统)上运行它:

 $./MyApp 

对于Windows(如果您需要它),文件名将是MyApp.exe

更多关于这里: 包装和代码保护 。