OSX - 打包基于shell的交互式二进制文件

时间:2015-04-18 04:57:14

标签: node.js macos

我创建了一个小型NodeJS脚本,使用EncloseJS进行编译,以便应用程序成为自己的二进制文件。该应用程序旨在在终端中运行并与用户交互。我想将它打包在.app中,这样就像普通用户可以运行的完整应用程序一样。

我该如何解决这个问题?到目前为止,我一直尝试使用混合结果的Platypus,因为它似乎没有正确退出。

2 个答案:

答案 0 :(得分:2)

尝试以下方法:

  • 使用[Apple]Script Editor创建新脚本并将其另存为应用程序
  • 放置二进制文件 - 让我们将其称为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

运行应用程序时,嵌入式二进制文件将在您可以与之交互的新终端窗口中打开。

& "; exit"附加到do script命令,以便在二进制文件终止时自动关闭终端窗口。

但请注意,应用程序仅用作嵌入式二进制文件的启动器

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

有很多方法可以解决这些问题(菜单除外),但需要额外的工作 - 见下文。


解决上述问题的解决方案,以获得更高度集成的体验

  • 它使包装器应用程序保持打开状态(显示自己的Dock图标)。
  • 当应用程序被激活时,将激活中继到启动的终端窗口,运行嵌入式二进制文件(例如,点击Dock图标)
  • 当启动的终端窗口关闭时,包装器应用程序会自动终止。

但是,它有限制

  • 遗憾的是,要继续激活,需要 GUI脚本,这需要在任何给定计算机上进行一次性授权和管理权限;首次启动时会提示用户,但需要几个步骤。
  • 为了使应用程序能够在单击时快速中继激活并在终端窗口关闭时快速退出,必须经常调用其​​on idle事件处理程序,这会消耗CPU资源,尽管CPU上的额外负载非常小 - 请参阅下面的源代码中的注释。

<强>说明:

  • 使用[Apple]Script Editor创建新脚本并将其另存为保持打开 应用程序
    • Save As对话框中,选择格式Application并选中Stay open after run handler复选框。
  • 放置二进制文件 - 让我们将其称为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

答案 1 :(得分:0)

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

$ jx package myapp.js MyApp -native

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

$./MyApp

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

有关此内容的更多信息:Packaging & Code Protection