如何创建OSX应用程序以包装对Shell脚本的调用?


10

我的目标是在zip文件中包含相当于快捷方式的内容,而不是告诉客户打开Terminal并运行Shell脚本。

我的可部署程序基本上是这样的:

$ unzip Deliverable.zip 
$ cd Deliverable; ls
app.jar run.sh

脚本run.sh

#!/bin/sh
java -jar app.jar

目录中还有更多内容。只需说我需要从Deliverable目录运行脚本,因为我需要访问相对于它的路径。但是,我不能保证客户会在哪里打开Deliverable.zip(可能是主目录,可能就在Downloads目录中,等等)。

我发现描述了如何在Automator中创建新的工作流程,然后将其另存为应用程序以启动Shell脚本。我试图包裹run.sh它,但是它说找不到run.sh

有人建议我使用applescript,还向我发送了有关如何使用applescript切换到当前目录的链接。自动化器中有一个applescript“操作”;因此我以此创建了一个新的工作流程,并将其保存为应用程序。看起来像这样:

自动化applescript程序

编码:

on run {input, parameters}
    tell application "Finder"
        set current_path to container of (path to me) as alias
    end tell

    do shell script "java -jar app.jar" 

    return input
end run

这是我运行它时遇到的错误:

欢迎来到2015

来吧,这应该很简单。我在这里做错了什么?


好吧,我刚刚发布了一个带有更简单的applescript的更新,但是看到我被grgarside认为对您更有效的答案被打败了。:-)
markhunte 2015年

这个问题的标题并不代表实际的问题,因此我投了反对票。问题更狭窄:问题在于解决错误消息“不再支持PowerPC应用程序”的问题,这就是问题标题中的内容。我实际上正在寻找有关如何创建应用程序捆绑包的答案。OP知道如何创建捆绑包,但遇到错误。
杰森

Answers:


4

将.sh文件重命名为.command,然后可以cd到.command文件所在的目录,并在文件开头添加以下内容:

cd "$(dirname $BASH_SOURCE)"

7

我可以看到那里有几处错误。

首先,您打开了一个工作流而不是一个应用程序。

在选择Automator文件类型时,应选择Application。

在此处输入图片说明

由于您没有更改目录,因此您拥有的代码将无法按预期工作。(光盘)。

在已有的代码中,它所要做的就是将路径作为别名并将其存储在变量current_path中,并以不适合unix命令的格式存储 。

但是您不使用它。

因此,当前目录很可能是您的主文件夹

在此阶段,尚无法确定它正在尝试启动什么。

如果我按您的要求运行,我会得到。

在此处输入图片说明

因为我没有安装Java,所以这很有意义。但是,如果我不这样做,就不会期望它找到正确的文件。

Applescript需要看起来像这样。

on run {input, parameters}
    tell application "Finder"
        set current_path to container of (path to me) as alias
    end tell

    do shell script "cd " & quoted form of (POSIX path of current_path) & " ;ls | open -fe"

    return input
end run 

在我的例子中

do shell script "cd " & quoted form of (POSIX path of current_path) & " ;/bin/ls | /usr/bin/open -fe"

我在变量current_path中 cd到别名 的POSIX路径

即从“别名”“ Macintosh HD:Applications:””到 “ / Applications /”

quoted form of 转义使用引号的路径。

我已经使用了/ bin / ls命令并将其通过管道传递到TextEdit stdin中打开处,作为此处的演示,因此您可以测试一下是否到达所需的区域。

您将使用类似的东西;

do shell script "cd " & quoted form of (POSIX path of current_path) & " ;\"java -jar app.jar\""

更新:

另一种方法是只使用纯Applescript。

on run {input, parameters}
    tell application "Finder"
        set current_path to container of (path to me)

        set theFile to (current_path) as alias

        open file "java -jar app.jar" of theFile
    end tell


end run

这非常接近解决方案。我确认ls | open代码肯定会打开我想要的目录,这很棒。但是,当我打电话给open时Client.app,我得到:LSOpenURLsWithRole() failed with error -10665 for the file <path-to-Client.app> -对该错误意味着建议权限问题的一些搜索进行了检查,+x并设置了标志。我也尝试过这个,但是没有用(有同样的错误)。
2015年

请注意,Client.app从Finder 中打开(双击)也会导致相同的PowerPC错误弹出窗口。
2015年

@emptyset I call open Client.app这是Automator应用程序。据我了解,在自动化器中,您有applescript代码:do shell script "cd " & quoted form of (POSIX path of current_path) & " ;\"java -jar app.jar\""。那么,您在哪里使用open命令?据我了解,您正在做什么,您不需要使用它。客户端将使用该应用程序双击,该应用程序将运行java
markhunte 2015年

我通过以下两种方式进行了测试:从命令行:$ open Client.app和双击。您的调用版本可以ls | open -fe工作,但是当我将其更改为java -jar app.jar它时,会出现该错误。
2015年

@emptyset trydo shell script "cd " & quoted form of (POSIX path of current_path) & " ; " & quoted form of "java -jar app.jar"
markhunte

6

脚本路径

在AppleScript中,您需要在发出Java命令之前更改当前的工作目录(cwd)。使用AppleScript行执行此操作,例如:

do shell script "cd " & quoted form of (POSIX path of file_path) & " && java -jar app.jar"

&&是很重要的。如果cd成功,java命令将在正确的cwd内启动。如果cd失败,该java命令将不会运行。

您可能会遇到的问题包括:

  • 转义传递给的POSIX路径cd; 用户将在其路径中具有奇怪命名的文件夹和空格。
  • cd可能会失败; 将AppleScript包装在try块中,以捕获一些错误并警告用户。

佩尔

就个人而言,我将使用简短的perl脚本来代替bash脚本。

#!/usr/bin/env perl

use strict;
use warnings;
use FindBin qw($Bin); # $Bin is a path to the script's parent folder

`cd "$Bin" && java -jar app.jar`;

有很多更好的方法可以编写此perl片段,但这应该可以工作。

自动化应用

最好的方法是使用Automator方法解决问题。@markhunte的答案讨论了如何修复路径和创建应用程序。这应该为您提供大部分帮助。

另请参阅AppleScript相对于脚本位置的路径

appify-从shell脚本创建最简单的Mac应用程序

另外,您可以使用Thomas Aylott的appify脚本将您的Shell脚本捆绑到OS X应用程序中。Mathias Bynen的文章介绍了如何使用脚本,如何从Shell脚本创建简单的Mac应用程序

#!/bin/bash

if [ "$1" = "-h" -o "$1" = "--help" -o -z "$1" ]; then cat <<EOF
appify v3.0.1 for Mac OS X - http://mths.be/appify
Creates the simplest possible Mac app from a shell script.
Appify takes a shell script as its first argument:
    `basename "$0"` my-script.sh
Note that you cannot rename appified apps. If you want to give your app
a custom name, use the second argument:
    `basename "$0"` my-script.sh "My App"
Copyright (c) Thomas Aylott <http://subtlegradient.com/>
Modified by Mathias Bynens <http://mathiasbynens.be/>
EOF
exit; fi

APPNAME=${2:-$(basename "$1" ".sh")}
DIR="$APPNAME.app/Contents/MacOS"

if [ -a "$APPNAME.app" ]; then
    echo "$PWD/$APPNAME.app already exists :("
    exit 1
fi

mkdir -p "$DIR"
cp "$1" "$DIR/$APPNAME"
chmod +x "$DIR/$APPNAME"

echo "$PWD/$APPNAME.app"

可以为该脚本提供社区贡献的改进:

代码签名

创建应用程序捆绑包后,应该对其进行代码签名。经过代码签名的应用程序将启动,而无需您的客户端禁用Gatekeeper。

使用Apple Developer ID和以下codesign命令对应用程序进行代码签名:

codesign -s <identity> -v <code-path> 

代码签名是OS X中使用的一种安全技术,它使您可以证明自己创建了一个应用程序。应用程序签名后,系统可以检测到该应用程序的任何更改-无论更改是意外引入还是由恶意代码引入。

在Apple Developer网站上了解有关代码签名的更多信息


感谢您提供代码签名提示;我现在正在调查并测试appify脚本!
2015年

申请脚本无效;相同的路径问题
emptyset

@emptyset我添加了路径和perl部分。将路径问题分成一个新的问题可能也是值得的。如果可以解决此问题,则可以使用Automator或appify脚本。
格雷厄姆·米尔恩


4

您可以更改run.shrun.command并让用户双击它吗?


差不多了!但是,它是从用户主目录(cd ~)的上下文中运行文件的,这导致该文件失败。
2015年

1
@emptyset使用$ BASH_SOURCE,请参阅apple.stackexchange.com/a/201482
grg

1

这是我对您所要实现的目标的理解。该代码是有目的的。

您所需要做的就是将代码复制到Applescript编辑器,进行所需的任何更改并将其保存为应用程序。

至于不支持有关PowerPC应用程序的对话框,我不知道。您可以从命令行运行它吗?我会先检查一下以确认该应用程序正常工作。

#
# STEP 1: locate and confirm zip file exists
#
#   This is long winded on purpose. It is meant to save the user some scrolling and 
#   and a click... Isn't this what computers are for to save time? :)
#

# Zip file name 
set zipname to "Deliverable.zip"

# Locate the zip file
set zippath to POSIX path of (choose folder)
log zippath
set qzippath to quoted form of zippath
log qzippath
set zipfile to (zippath & zipname)
set qzipfile to quoted form of (zippath & zipname)
log qzipfile

# Check for the file... Use either test not both :)
try
    # using shell test - case sensetive
    do shell script "test -f " & qzipfile

    # using native test - doesn't like quoted forms and case insensetive...
    POSIX file zipfile as alias
on error
    display dialog "ERROR: Zip file was not found at selected folder." as text ¬
        buttons {"OK"} with icon caution ¬
        with title "Alert"
    return
end try


#
# STEP 2: Zip found. Unzip it
#
try
    # Add " -d Deliverable" at the end to force directory  
    # unzip -o to force overwrite for testing....
    do shell script "cd " & qzippath & "; unzip -o " & zipname
on error eStr
    display dialog "ERROR: Failed to unzip file. Message returned was, " & ¬
        return & return & eStr as text ¬
        buttons {"OK"} with icon caution ¬
        with title "Unzip Error"
    return
end try


#
# STEP 3: Run script 
#
set dpath to (zippath & "Deliverable/")
log dpath
set qdpath to quoted form of dpath
log qdpath
try
    do shell script "cd " & qdpath & ";  sh ./run.sh"
on error eStr
    display dialog "ERROR: Failed to launch script. Message returned was, " & ¬
        return & return & eStr as text ¬
        buttons {"OK"} with icon caution ¬
        with title "Deliverable Script Launch"
    return
end try
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.