Как дождаться, пока osascript выдаст результат - PullRequest
0 голосов
/ 10 июля 2020

иногда кажется, что мой код AppleScript не работает, на других машинах он работает.

Я запускаю этот код AppleScript как heredo c изнутри сценария оболочки. Сценарий оболочки - это сценарий после установки, который запускается установщиком pkg и запускается как root:

#!/bin/sh
set -x
logfile="/Library/Logs/EZEEP Connector Installer.log"

LogMessage()
{
  echo $(date) $1 >> "${logfile}"
}

LogMessage "................................."
LogMessage "Installer postinstall started ..."
LogMessage "................................."

# set file system tag 'Printing' on app bundle:
/usr/bin/osascript <<'EOD'
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

on addTags:tagList forPath:posixPath -- add to existing tags
    set aURL to current application's |NSURL|'s fileURLWithPath:posixPath -- make URL
    #display dialog aURL as string
    -- get existing tags
    
    set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
    if theTags is not missing value then -- add new tags
        set tagList to (theTags as list) & tagList
        set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
    end if
    aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
    
end addTags:forPath:

tell application "Finder"
    set thePath to (POSIX path of (application file id "com.thinprint.ezeep.Connector" as alias))
    
    my addTags:{"Printing"} forPath:thePath
end tell
EOD

#sleep 10


sudo -u ${USER} /usr/bin/osascript -e 'tell application "/Applications/ezeep Connector.app" to launch'

LogMessage "................................."
LogMessage " Installer postinstall finished ."
LogMessage "................................."

Иногда целевой пакет приложений получает тег, иногда нет. Если я раскомментирую последний сон в моем примере кода, то все будет работать, как ожидалось.

Даже на двух разных виртуальных машинах у нас всегда создается тег на одной виртуальной машине и не удается создать на другой.

Есть ли правильный способ дождаться результата операции добавления тега, а затем продолжить выполнение сценария? Или команда sleep 10 - надежное решение, позволяющее запустить ее на десятках или даже сотнях компьютеров Mac без сбоев даже на нескольких?

С уважением,

Роберт

1 Ответ

0 голосов
/ 10 июля 2020

Во-первых, всегда рекомендуется избегать написания сценариев для Finder (загруженного приложения, которое может вызывать странные задержки и ошибки в сценариях). Поскольку вы все равно используете AppleScriptObj C, вы можете получить нужный URL из NSWorkspace. Затем все, что вам нужно сделать, это добавить команду repeat / check / delay l oop, которая проверяет, добавлен ли тег.

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set theURL to my findAppURLFromID:"com.thinprint.ezeep.Connector"
my addTags:{"Printing"} forURL:theURL
my checkTag:"Printing" forURL:theURL

(* get app package URL from NSWorkspace *)
on findAppURLFromID:appID
    set sharedWorkspace to (current application's NSWorkspace's sharedWorkspace)
    set appURL to sharedWorkspace's URLForApplicationWithBundleIdentifier:appID
    return appURL
end findAppURLFromID:

(* altered to accept URL directly *)
on addTags:tagList forURL:aURL
    set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
    if theTags is not missing value then
        set tagList to (theTags as list) & tagList
    end if
    (*
        I moved the following statement out of the 'if' block. This would not be
        called if the package file has no tags, so the script would feed an unaltered
        AppleScript list to 'setResourceValue:forKey:error'. That may work, dunno
        but better to put everything into the correct object format
    *)
    set tagList to (current application's NSOrderedSet's orderedSetWithArray:tagList)'s allObjects() -- delete any duplicates
    aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end addTags:forURL:

(* checks every half second to see if the list of tags contains "Printing" *)
on checkTag:tagName forURL:aURL
    repeat 120 times
        set {theResult, theTags} to aURL's getResourceValue:(reference) forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
        set tagList to (theTags as list)
        if tagList contains "Printing" then return
        delay 0.5
    end repeat
    display alert "tagging timed out after 1 minute"
end checkTag:forURL:

Я исправил одну (потенциальную) ошибку в вашем скрипте; см. встроенный текстовый комментарий.

Предполагается, что вы добавляете только один тег. Если вы хотите добавить (и проверить) несколько тегов, вам потребуется сложность checkTag:forURL. Кроме того, я мало что сделал с обработкой ошибок (в любом случае, когда по какой-то причине добавление тега не удалось), кроме как подбросить предупреждение. Я использовал случайное повторение l oop, чтобы он не продолжался бесконечно при неудаче, но вы можете захотеть, чтобы он отказывался тихо или в этот момент сделал что-то еще.

...