Как я могу перезапустить запущенное в данный момент приложение с помощью AppleScript?

Я создал приложение с действием «Запустить AppleScript» в Automator.

Я создал службу в Automator, которая запускает вышеупомянутое приложение.

Служба запускается сочетанием клавиш, назначенным в Системных настройках.

Приложение представляет пользователю серию диалогов. Я хотел бы дать пользователю возможность перезапустить все приложение в середине приложения. Например, предположим, что следующая строка была строкой 100 кода:

set buttonChoice to button returned of (display alert "Do you want to replace this entry?" as critical buttons {"Start over", "No", "Yes"})

   if buttonChoice is "Start over" then     
      <this is where I need your help, Ask Different>
   end if

Когда я говорю «перезагрузить» или «начать сначала», я имею в виду, что хочу вернуть пользователя к начальному диалогу приложения, то есть к самой первой строке кода приложения.

Можно ли это сделать с помощью AppleScript?

При необходимости это расположение файла приложения:

/Приложения/Мои приложения/Мой журнал.приложение

Можно как-то поподробнее объяснить? Потому что я опубликовал ответ, и в комментарии мне было указано, что мой ответ на самом деле не решает вашу проблему.
« Вы хотите заменить эту запись?» alert выше — это, например, десятое диалоговое окно, представленное пользователю. Я хотел бы, чтобы приложение полностью перезапускалось с самой первой строки кода, если buttonChoice имеет значение «Начать сначала» , как подозревал @user3439894. Прошу прощения, если это было неясно.
Итак, ваше «My Log.app» в основном просто содержит кучу разных последовательных диалогов? Я думаю, это то, что вы говорите, поэтому я отредактирую свой первоначальный ответ. Спасибо
Он выполняет другие функции, такие как запись текста в файл и чтение текста из файла, но, да, «Мой Log.app» — это просто набор различных последовательных диалогов.

Ответы (3)

В следующем примере кода предполагается, что действие «Выполнить AppleScript» начинается с команды без какого-либо списка , например, и, следовательно, завершает сценарий командой :on run {input, parameters}end run

on run

    (*
            This comment represents the e.g. previous 99 lines of code.
        *)

    set buttonChoice to button returned of (display alert "Do you want to replace this entry?" as critical buttons {"Start over", "No", "Yes"})
    try
        if buttonChoice is "Start over" then
            return on run
        end if
    end try

    (*
            This comment represents the rest of the code in the script.
        *)

end run

Обратите внимание, что я тестировал это в macOS Sierra 10.12, и хотя кажется, что он начинается сначала, потому что, если вы нажмете кнопку «Начать сначала», он зациклится, пока вы не выберете другой вариант, я не уверен, что это лучший способ реализовать это. Я говорю это, потому что я не знаю структуру и кодирование остальной части скрипта, и это может иметь значение, наряду с тем фактом, что при тестировании другого кода на каждой стороне этого я мог сбой приложения в зависимости от того, что было происходит, если я зациклился более одного раза в этот момент.

Итак, с учетом сказанного, я предлагаю это как нечто для тщательного тестирования, прежде чем внедрять его в окончательный код.

Я бы предложил просто разрешить пользователю завершить приложение с сообщением о ручном перезапуске, нажав комбинацию клавиш, чтобы запустить службу, которая запускает приложение, выполняя цикл, подобный этому.

Обновлять:

Я начал с решения пользователя 3439894 в качестве основы, но мне пришлось внести несколько изменений, чтобы улучшить функцию «перезагрузки» для моего приложения (как рекомендовал пользователь 3439894).

Сначала, когда я напрямую скопировал решение, у меня возникла проблема, когда код запускался еще раз после завершения перезапуска. Но методом проб и ошибок мне удалось интуитивно найти решение.

Вот что я сделал, чтобы заставить его работать:

Я помещаю следующую строку перед самой первой строкой основной части моего кода:

try

и в конце моего основного кода я поставил:

on error errStr number errorNumber
end try

По указанию пользователя 3439894 мне также пришлось удалить строку по умолчанию из этого места (и в любом случае в этом приложении return inputмне это не нужно ).return input

Затем, после каждого диалога, в котором я хотел, чтобы пользователю была представлена ​​возможность начать все сначала в этом диалоге, я поставил:

if buttonChoice is "Start over" then
    return on run
end if

После этих шагов функция «перезагрузки» работает отлично! Он не повторяется дополнительное количество раз в конце и никогда не выдает пользователю какую-либо ошибку. Я также могу зациклить приложение несколько раз, если захочу, без ошибок или проблем.

Он отлично работает даже тогда, когда диалоги расположены в подпрограммах. Обратите внимание, что мои подпрограммы не находятся внутри tryблока.


Что происходит, когда вам нужно использовать inputв вашем AppleScript?

Мне удалось найти обходной путь. Просто поместите код перезапуска в подпрограмму:

on run {input, parameters}
    restartSubroutine()
    return input
end run

on restartSubroutine()
    set buttonChoice to button returned of (display alert "Do you want to replace this entry?" as critical buttons {"Start over", "No", "Yes"})

    try
        if buttonChoice is "Start over" then
            return on run restartSubroutine()
            (*
            The following lines work as well:
            return on restartSubroutine()
            return run restartSubroutine()
            *)
        end if
    end try
end restartSubroutine

Конечно, функция перезапуска вернет вас только к началу этой подпрограммы, а не к первой строке основного тела. Но, если вам не нужно ссылаться на inputконец вашего скрипта, это может сработать для вас, чтобы у вас была функциональная кнопка перезапуска вплоть до того момента, когда вам нужно input.


Редактировать:

Я только что придумал еще лучший обходной путь:

on run {input, parameters}
    restartSubroutine(input)
    return input
end run

on restartSubroutine(input)
    set buttonChoice to button returned of (display alert "Do you want to replace this entry?" as critical buttons {"Start over", "No", "Yes"})

    if buttonChoice is "Start over" then
        return restartSubroutine(input)
    end if      
end restartSubroutine

Если вы отправляете inputподпрограмме, вы можете иметь функцию перезапуска, имея доступ к inputсодержимому. Беспроигрышный.

@user3439894 user3439894 Это решение подходит или вы видите потенциальные проблемы с ним?
Если он работает у вас так, как нужно/хотелось, и не вызывает ошибок, то я не вижу никаких проблем с его использованием.

Я обнаружил еще один способ перезапустить AppleScript.

Этот метод не «лучше», чем другие предложенные методы; это просто еще один способ приблизиться к вещам. Вот как вы можете перезапустить файл .scpt в AppleScript:

if buttonChoice is "Start over" then
    run script "/Users/Me/Desktop/My script.scpt"
    error number -128 (* user cancelled *)
end if

Или, альтернативно:

if buttonChoice is "Start over" then
    run script (path to me)
    error number -128 (* user cancelled *)
end if

Этот код просто создает еще один экземпляр работающего в данный момент файла AppleScript .scpt, а затем закрывает текущий экземпляр.

Я узнал об этом run scriptиз комментария пользователя Camelot на следующей веб-странице:

Вызовите другой Applescript | Сообщества Apple


С той же базовой предпосылкой, если вы хотите перезапустить файл .app с помощью AppleScript, используйте это:

if buttonChoice is "Start over" then
    do shell script "open -n " & quoted form of "/Users/Me/Desktop/My app.app"
    error number -128 (* user cancelled *)
end if

Или, альтернативно:

if buttonChoice is "Start over" then
    do shell script "open -n " & (quoted form of (POSIX path of (path to me)))
    error number -128 (* user cancelled *)
end if

Позволяет -nоткрыть новый экземпляр приложения, даже если экземпляр этого приложения уже запущен. Это -nнеобходимо, потому что, говоря практически, приложение AppleScript технически закрывается после создания второго экземпляра, даже если это может показаться не так, исходя из того, что вы видите на своем экране.


Когда следует использовать этот метод перезапуска?

Это немного запутает, так что потерпите меня...

У меня есть файл AppleScript .scpt, который автоматически запускается, когда мой компьютер выходит из спящего режима. ( Для этого я использую SleepWatcher .)

Этот файл .scpt вызывает определенную подпрограмму из другого файла .scpt; он пропускает весь сценарий и запускает только тот код, который находится в одной конкретной подпрограмме. (Для этого я использую метод, описанный здесь .)

Этот второй файл .scpt изобилует кнопками «Начать сначала» почти в каждом диалоговом окне, в которых используются:

return on run

для достижения эффекта перезапуска. (Этот метод перезапуска был предоставлен в предыдущем ответе на этот вопрос.)

Теперь проблема в том, что хотя мой первый файл .scpt действительно успешно перезапускает второй файл .scpt, когда return on runон используется во втором файле .scpt, после завершения сценария пользователю отображается диалоговое окно, содержащее следующую ошибку. :

«скрипт» не понимает «возврат»

Честно говоря, эта ошибка имеет смысл; первый файл .scpt не может полностью понять значение return, потому что он никогда не запускал другой сценарий. Он запускал только одну подпрограмму другого сценария.

Эта ошибка задела меня. Итак, я еще немного повозился с кодом и узнал о run script. Конкретный тип сценария, который я только что объяснил, — это то, где run scriptметод перезапуска действительно сияет.

Простой run scriptметод спасает ситуацию: он перезапускает второй файл .scpt без необходимости вызывать команду returnв процессе. Таким образом, этот метод полностью безошибочен, даже если он выполняется за пределами его более крупного окружающего кода. Это единственный метод на этой странице, который может это сделать, так как другие методы зависят от return.