Bug della barra di avanzamento di AppleScript: come impedire la finestra di dialogo di avanzamento?

6

Il bug:

Quando la finestra di dialogo di avanzamento di AppleScript è seguita da una finestra di dialogo, la finestra di avanzamento continua a persistere, anche se tutte le fasi di avanzamento sono state completate e la barra di avanzamento è piena. Si attarderà fino a quando lo script non sarà stato cancellato, fino a quando lo script non sarà completato, o fino a quando non ci saranno altre finestre di dialogo nello script.

Questo errore non può essere visto durante l'esecuzione del codice da Script Editor.app, perché in Script Editor non apparirà una finestra di dialogo. Invece, un indicatore di avanzamento a forma di torta è integrato nella parte inferiore della finestra di script.

Come riprodurre il bug:

Salva il seguente AppleScript codice come file .app:

(Il file deve essere un file .app, poiché i file scpt non possono visualizzare le finestre di dialogo dell'avanzamento.)

set n to 5

set progress total steps to n
set progress description to "Script Progress"
set progress additional description to "Additional description"

repeat with i from 1 to n
    delay 0.1
    set progress completed steps to i
end repeat

display dialog "The progress dialog should be gone at this point."

All'avvio dell'applicazione, vedrai quanto segue:

La domanda:

Esiste una soluzione alternativa per forzare la chiusura della finestra di avanzamento una volta completata, in modo che le finestre di dialogo aggiuntive possano essere posizionate dopo la finestra di avanzamento, senza che la finestra di dialogo di avanzamento sia ancora visibile?

Quello che ho provato:

Ho provato ad affrontare il problema interpretando semplicemente la finestra di avanzamento come una "finestra" dell'app.

Se si esegue il seguente codice in un file AppleScript separato, mentre entrambe le finestre di dialogo di ProgressBarTest.app sono sullo schermo (come nell'immagine precedente):

tell application "System Events"
    set allWindows to name of window of processes whose visible is true
end tell 

return allWindows

imparerai che ProgressBarTest.app ha 2 finestre aperte. I titoli di queste finestre sono:

{"", "ProgressBarTest.app"}

La prima finestra in questa lista si riferisce alla finestra di dialogo display dialog . La seconda finestra in questo elenco, denominata ProgressBarTest.app , è la finestra di dialogo di avanzamento.

Ho quindi tentato di chiudere questa finestra di dialogo di avanzamento "finestra" utilizzando AppleScript (come si può fare per qualsiasi finestra di applicazione standard). Ma il seguente codice:

tell application "System Events" to tell process "ProgressBarTest.app"
    if exists window "ProgressBarTest.app" then
        close window "ProgressBarTest.app"
    end if
end tell

darà all'utente un errore. Il testo di questa finestra di dialogo di errore è:

Script Error

System Events got an error: window "ProgressBarTest.app" of process "ProgressBarTest.app" doesn’t understand the “close” message.

Mi sono reso conto che, se lo schermo è lo stesso punto di vista dello screenshot precedente, non è possibile chiudere manualmente la finestra di dialogo di avanzamento. Questo perché la finestra di dialogo display dialog ha la precedenza sulla finestra di avanzamento; la finestra di dialogo display dialog "cancella" (cioè, disabilita) tutti i pulsanti nella finestra di dialogo di avanzamento.

Quindi, per tener conto di ciò, nel codice ProgressBarTest.app, ho aggiunto un delay 5 direttamente sopra la riga display dialog "The progress dialog should be gone at this point." . Volevo vedere se potevo chiudere con successo la finestra di avanzamento, se la finestra di dialogo di avanzamento era l'unica finestra di dialogo attiva dell'applicazione.

Ho provato il seguente codice:

tell application "System Events" to tell process "ProgressBarTest.app"
    if exists window "ProgressBarTest.app" then
        click button 1 of window "ProgressBarTest.app"
    end if
end tell

Nel codice precedente, button 1 si riferisce al pulsante Stop che si trova nella finestra di dialogo di avanzamento. (In alternativa puoi usare button -4 o button 0 per fare riferimento a questo stesso pulsante.)

La buona notizia è che questo codice è stato chiuso correttamente dalla finestra di dialogo di avanzamento!

La cattiva notizia, tuttavia, è che quando viene premuto il pulsante Interrompi della finestra di dialogo di avanzamento, invece di chiudere solo la finestra di dialogo di avanzamento, l' intero script viene annullato. Questo è ovviamente indesiderabile.

La radice del problema è che la finestra di dialogo di avanzamento non contiene la "x" rossa; il pulsante circolare più a sinistra nella barra superiore di questa finestra di dialogo è sempre in grigio. In altre parole, non c'è modo di chiudere manualmente la finestra di avanzamento, senza terminare anticipatamente lo script.

Quindi, questo problema è più difficile da risolvere di quanto pensassi.

Sembra che il mio risultato desiderato sia impossibile da raggiungere.

OS X El Capitan, versione 10.11.6.

posta rubik's sphere 29.05.2017 - 22:20
fonte

1 risposta

4

Funziona per me sull'ultima versione di Sierra

SOLUZIONE 1

set n to 5

set progress total steps to n
set progress description to "Script Progress"
set progress additional description to "Additional description"

repeat with i from 1 to n
    delay 0.1
    set progress completed steps to i
end repeat
return
quit

on quit
    activate
    display dialog "The progress dialog should be gone at this point."
    continue quit -- allows the script to quit
end quit

Eccounmodopereseguirealcuniloopdiripetizioneprimacheloscriptsichiuda

setnto5setprogresstotalstepstonsetprogressdescriptionto"Script Progress"
set progress additional description to "Additional description"

repeat with i from 1 to n
    delay 0.1
    set progress completed steps to i
end repeat
return
quit

on quit
    activate
    display dialog "The progress dialog should be gone at this point."
    repeat 5 times
        my get_my_IP()
        my screenCaptureToDesktop()
        delay 1
    end repeat
    continue quit -- allows the script to quit
end quit


on get_my_IP()
    activate
    tell current application to display dialog (do shell script "curl ifconfig.co") with icon 2 buttons "OK" default button 1 with title "Your Current IP Address Is.." giving up after 5 -- "curl ifconfig.io"    -- alternate
end get_my_IP

on screenCaptureToDesktop()
    do shell script "/usr/sbin/screencapture \"" & ¬
        POSIX path of (path to desktop as string) & ¬
        "Screen Shot " & (current date) & ".png\""
end screenCaptureToDesktop

Aggiorna

SOLUZIONE 2

Lavorando su uno dei miei progetti, ho avuto uno di questi "EUREKA!" momenti. Ecco un approccio completamente diverso rispetto al mio codice in SOLUZIONE 1. L'approccio qui era quello di avvolgere la maggior parte del mio codice in oggetti o gestori di script, quindi chiamare quegli oggetti secondo necessità. In questa soluzione, ho salvato questo script come applicazione aperta, con gestori di esecuzione e idle espliciti. Parte del codice viene eseguita all'avvio dell'applicazione, ma la maggior parte dei comandi avviene effettivamente all'interno del gestore inattivo.

Penso che questa soluzione abbia più promesse della SOLUZIONE 1.

global allFiles, thisFile, theFileCount, ProgressBar, mainFolder, backupFolder, theDate

on run
    run ProgressBar
end run

on idle
    delay 0.2
    activate
    set theButton to button returned of (display dialog ¬
        "The progress dialog should be gone at this point." buttons {"QUIT", "CONTINUE"} ¬
        default button ¬
        "CONTINUE" with title ¬
        "BACKUP UTILITY" with icon 0 ¬
        giving up after 10)
    if theButton = "QUIT" then
        quit
    else if theButton = "" then
        quit
    else if theButton = "CONTINUE" then
        try
            run ProgressBar
        end try
    end if
    return 1
end idle

on quit
    --  Executed when the script quits
    continue quit -- allows the script to quit
end quit

script ProgressBar
    set mainFolder to choose folder with prompt ¬
        "PLEASE CHOOSE YOUR SOURCE FOLDER TO BACKUP"
    set backupFolder to choose folder with prompt ¬
        "PLEASE CHOOSE YOUR BACKUP DESTINATION FOLDER"
    set theDate to (current date) - (14 * days)

    tell application "Finder"
        set allFiles to entire contents of folder mainFolder as alias list
    end tell

    set theFileCount to count of allFiles

    set progress total steps to theFileCount
    set progress completed steps to 0
    set progress description to "Processing Files..."
    set progress additional description to "Preparing to process."

    repeat with theName from 1 to number of items in allFiles
        set this_item to item theName of allFiles
        tell application "Finder"
            duplicate this_item to backupFolder ¬
                with replacing
        end tell
        set progress additional description to ¬
            "Duplicating File " & theName & " of " & theFileCount & ¬
            " to folder " & backupFolder
        set progress completed steps to theName
    end repeat

    -- Reset the progress information
    set progress total steps to 0
    set progress completed steps to 0
    set progress description to ""
    set progress additional description to ""
end script

    
risposta data 30.05.2017 - 06:41
fonte

Leggi altre domande sui tag