Come posso riavviare un'applicazione attualmente in esecuzione con AppleScript?

4

Ho creato un'applicazione con un'azione "Esegui AppleScript" in Automator.

Ho creato un servizio in Automator che avvia la suddetta app.

Il servizio è attivato da una scorciatoia da tastiera, assegnata in Preferenze di sistema

L'applicazione presenta una serie di finestre di dialogo per l'utente. Vorrei dare all'utente la possibilità di riavviare l'intera applicazione a metà dell'applicazione. Ad esempio, supponiamo che la seguente riga fosse la riga 100 del codice:

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

Quando dico "restart" o "start over", intendo che voglio restituire l'utente alla finestra di dialogo iniziale dell'applicazione, cioè la primissima riga di codice dell'applicazione.

Questo può essere fatto usando AppleScript?

Se necessario, questa è la posizione del file dell'applicazione:

/Applications/My Applications/My Log.app

    
posta rubik's sphere 23.01.2017 - 06:47
fonte

3 risposte

2

Il seguente esempio di codice presuppone che l'azione Esegui AppleScript inizi con un on run comando senza alcun elenco , ad es {input, parameters} e di conseguenza termina lo script con 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

Si noti che ho provato questo in macOS Sierra 10.12 e mentre sembra ricominciare da capo, perché se si preme il pulsante "Start over" esso si ripete finché non si seleziona un'altra scelta, non sono sicuro che questo sia il modo migliore per implementalo. Lo dico perché non conosco la struttura e la codifica del resto della sceneggiatura e che può fare la differenza insieme al fatto che durante il test di altri codice su ciascun lato di questo, sono stato in grado di arrestare l'app in modo anomalo a seconda di cosa stava succedendo se eseguivo un ciclo più di una volta a questo punto.

Quindi, detto questo, sto offrendo questo come qualcosa da testare completamente prima di implementarlo nel codice finale.

Suggerirei semplicemente di consentire all'utente di chiudere l'app con un messaggio per riavviarlo manualmente premendo il tasto-combo per attivare il servizio che avvia l'app oltre l'implementazione di un loop come questo.

    
risposta data 23.01.2017 - 23:13
fonte
1

Aggiornamento:

Ho iniziato con la soluzione di user3439894 come base, ma ho dovuto apportare un paio di modifiche per perfezionare la funzione "restart" per la mia applicazione (come raccomandato dall'utente3439894).

All'inizio, quando ho copiato direttamente la soluzione, stavo riscontrando un problema in cui il codice veniva eseguito una volta in più dopo il completamento della corsa riavviata. Ma, per tentativi ed errori, sono riuscito a intuire una soluzione.

Ecco cosa ho fatto per farlo funzionare:

Ho messo la seguente riga prima della prima riga del corpo principale del mio codice:

try

e alla fine del mio codice principale, inserisco:

on error errStr number errorNumber
end try

Come richiesto dal user3439894, ho anche dovuto eliminare la riga return input di default da questa posizione (e non ho avuto bisogno di return input in questa applicazione, comunque).

Quindi, dopo ogni finestra di dialogo di cui volevo che l'utente fosse presentato con l'opzione di ricominciare da quella finestra, ho messo:

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

Seguendo questi passaggi, la funzione "restart" funziona perfettamente! Alla fine non ripete un numero extra di volte, né presenta mai all'utente errori. Posso anche eseguire il loop dell'applicazione più volte, se lo desideri, senza errori o problemi.

Funziona perfettamente anche quando le finestre di dialogo si trovano nelle subroutine. Tieni presente che le mie subroutine sono non nel blocco try .

Che cosa accade quando devi utilizzare input nel tuo AppleScript?

Sono riuscito a scoprire una soluzione alternativa. È sufficiente posizionare il codice di riavvio all'interno di una subroutine:

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

Ovviamente, la funzione di riavvio ti riporterà solo all'inizio della subroutine, non alla prima riga del corpo principale. Ma, se non hai bisogno di fare riferimento a input fino alla fine del tuo script, questo potrebbe funzionare per te in modo da poter avere un pulsante di riavvio funzionale fino al momento in cui hai bisogno di input .

Modifica:

Ho appena trovato una soluzione ancora migliore:

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

Se si invia input a una subroutine, allora si può avere una funzione di riavvio mentre si ha accesso ai contenuti di input . Win-win.

    
risposta data 03.02.2017 - 02:46
fonte
0

Ho scoperto un altro metodo per riavviare un AppleScript.

Questo metodo non è "migliore" degli altri metodi che sono stati forniti; è semplicemente un altro modo di affrontare le cose. Ecco come puoi riavviare un file .scpt in AppleScript:

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

Oppure, in alternativa:

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

Questo codice crea semplicemente un'altra istanza del file .scpt di AppleScript correntemente in esecuzione e quindi chiude l'istanza corrente.

Ho saputo di run script da un commento da parte dell'utente Camelot sulla seguente pagina web:

Chiama un altro AppleScript | Comunità Apple

Con la stessa premessa di base, se vuoi riavviare un file .app usando AppleScript, usa questo:

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

Oppure, in alternativa:

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

Il -n consente di aprire una nuova istanza dell'applicazione, anche se è già in esecuzione un'istanza di questa applicazione. Il -n è necessario perché, in pratica, l'app AppleScript si chiude tecnicamente dopo che è stata creata la seconda istanza, anche se questo potrebbe non sembrare il caso in base a ciò che si vede sullo schermo.

Quando si dovrebbe utilizzare questo metodo di riavvio?

Questo diventerà un po 'confuso, quindi abbi pazienza con me ...

Ho un file .scpt di AppleScript che viene eseguito automaticamente quando il computer si riattiva dallo stato di stop. (Io uso SleepWatcher per realizzare questo.)

Questo file .scpt chiama una subroutine specifica di un diverso file .scpt; salta l'intero script e esegue solo il codice che si trova in una subroutine specifica. (Per farlo, uso il metodo Descritto qui .)

Questo secondo file .scpt è pieno di pulsanti "Start over" in quasi tutti i dialoghi, utilizzando:

return on run

per ottenere l'effetto di riavvio. (Questo metodo di riavvio è stato fornito in una precedente risposta a questa domanda.)

Ora, il problema è che, mentre il mio primo file .scpt , infatti, riavvia con successo il secondo file .scpt quando return on run è usato nel secondo file .scpt, una volta che lo script ha completato , una finestra di dialogo contenente il seguente errore viene presentata all'utente:

«script» doesn’t understand the “return”

Per essere onesti, questo errore ha senso; il primo file .scpt non può comprendere appieno il significato di return , perché non è mai stato realmente in esecuzione l'altro script. Stava solo eseguendo una subroutine dell'altro script.

Questo errore mi ha infastidito. Così, ho fatto ancora un po 'di problemi con il codice e ho imparato a conoscere run script . Il tipo specifico di scenario che ho appena illustrato è dove il metodo di riavvio run script brilla veramente.

Il semplice metodo run script salva il giorno: riavvia il secondo file .scpt e senza dover richiamare il comando return nel processo. Pertanto, questo metodo è completamente privo di errori, anche quando viene eseguito al di fuori del suo codice più ampio e circostante. Questo è l'unico metodo in questa pagina in grado di farlo, poiché gli altri metodi dipendono da return .

    
risposta data 09.03.2017 - 04:39
fonte

Leggi altre domande sui tag