Domanda:
Bug della barra di avanzamento di AppleScript: come evitare che la finestra di dialogo di avanzamento rimanga?
rubik's sphere
2017-05-30 01:20:52 UTC
view on stackexchange narkive permalink

Il bug:

Quando la finestra di dialogo di avanzamento di AppleScript è seguita da una finestra di dialogo, la finestra di dialogo di avanzamento rimane ancora aperta, anche se tutti i passaggi di avanzamento sono stati completati e la barra di avanzamento è piena. Rimarrà fino a quando lo script non sarà stato annullato, fino a quando lo script non sarà stato completato o fino a quando non saranno presenti ulteriori finestre di dialogo nello script.

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


Come riprodurre il bug:

Salva il seguente codice AppleScript come file .app:

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

  imposta n su 5

imposta avanzamento totale passi a n
imposta la descrizione dell'avanzamento su "Avanzamento script"
imposta la descrizione aggiuntiva dell'avanzamento su "Descrizione aggiuntiva"

ripetere con i da 1 a n
    ritardo 0.1
    imposta l'avanzamento dei passaggi completati su i
fine ripetizione

display dialog "La finestra di dialogo di avanzamento dovrebbe essere scomparsa a questo punto."
 

All'avvio dell'applicazione, vedrai quanto segue:


La domanda:

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


Cosa ho provato:

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

Se esegui il codice seguente in un file AppleScript separato, mentre entrambe le finestre di dialogo di ProgressBarTest.app sono sullo schermo (come nello screenshot sopra):

  indica all'applicazione "Eventi di sistema"
    imposta allWindows al nome della finestra dei processi il cui visibile è vero
fine raccontare

return allWindows
 

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

  {"", "ProgressBarTest.app"}
 

La prima finestra in questo elenco fa riferimento alla finestra di dialogo display dialog . La seconda finestra in questo elenco, intitolata ProgressBarTest.app , è la finestra di dialogo di avanzamento.

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

  indica all'applicazione "Eventi di sistema" di indicare al processo "ProgressBarTest.app"
    se esiste la finestra "ProgressBarTest.app" allora
        chiudere la finestra "ProgressBarTest.app"
    finisci se
fine raccontare
 

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

Script Error

Gli eventi di sistema hanno ricevuto un errore: la finestra "ProgressBarTest.app" del processo "ProgressBarTest.app" non comprende il messaggio "chiudi".

Mi sono reso conto subito che, se il tuo schermo è lo stesso punto di vista di quello dello screenshot qui sopra, non puoi nemmeno 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 "disattiva" (ovvero, disabilita) tutti i pulsanti nella finestra di dialogo di avanzamento.

Quindi, per tenere conto di questo, nel codice ProgressBarTest.app, ho aggiunto un ritardo 5 direttamente sopra la finestra di dialogo di visualizzazione "La finestra di dialogo di avanzamento dovrebbe essere scomparsa a questo punto."

/ code> riga. Volevo vedere se riuscivo a chiudere correttamente la finestra di dialogo di avanzamento, se la finestra di dialogo di avanzamento era l'unica finestra di dialogo attiva dell'applicazione.

Ho provato il seguente codice:

  indica all'applicazione "Eventi di sistema" di indicare al processo "ProgressBarTest.app"
    se esiste la finestra "ProgressBarTest.app" allora
        fare clic sul pulsante 1 della finestra "ProgressBarTest.app"
    finisci se
fine raccontare
 

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

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

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

La radice del problema è che la finestra di dialogo di avanzamento non contiene "x" rosse; il pulsante circolare più a sinistra nella barra superiore di questa finestra di dialogo è sempre disattivato. In altre parole, non è possibile chiudere manualmente la finestra di dialogo di avanzamento, senza anche terminare prematuramente lo script.

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

Sembra che il risultato desiderato sia impossibile da ottenere.


OS X El Capitan, versione 10.11.6.


Sei mai arrivato a una soluzione a questo?Hai esposto perfettamente il problema;sembra piuttosto il difetto di progettazione che Apple non avrebbe fornito un interruttore per la visibilità della barra di avanzamento.
@IvanX Non l'ho.
@IvanX ho pubblicato del codice in una risposta con una soluzione
Una risposta:
wch1zpink
2017-05-30 09:41:38 UTC
view on stackexchange narkive permalink

Per me funziona con l'ultima versione di Sierra

SOLUTION 1

  imposta n su 5

imposta avanzamento totale passi a n
imposta la descrizione dell'avanzamento su "Avanzamento script"
imposta la descrizione aggiuntiva dell'avanzamento su "Descrizione aggiuntiva"

ripetere con i da 1 a n
    ritardo 0.1
    imposta l'avanzamento dei passaggi completati su i
fine ripetizione
ritorno
smettere

quando esci
    attivare
    display dialog "La finestra di dialogo di avanzamento dovrebbe essere scomparsa a questo punto."
    continue quit: consente di chiudere lo script
fine esci
 

enter image description here

Ecco un modo per eseguire alcuni cicli di ripetizione prima che lo script si chiuda

  imposta n su 5

imposta avanzamento totale passi a n
imposta la descrizione dell'avanzamento su "Avanzamento script"
imposta la descrizione aggiuntiva dell'avanzamento su "Descrizione aggiuntiva"

ripetere con i da 1 a n
    ritardo 0.1
    imposta l'avanzamento dei passaggi completati su i
fine ripetizione
ritorno
smettere

quando esci
    attivare
    display dialog "La finestra di dialogo di avanzamento dovrebbe essere scomparsa a questo punto."
    ripetere 5 volte
        il mio get_my_IP ()
        il mio screenCaptureToDesktop ()
        ritardo 1
    fine ripetizione
    continue quit: consente di chiudere lo script
fine esci


su get_my_IP ()
    attivare
    indica all'applicazione corrente di visualizzare la finestra di dialogo (esegui lo script di shell "curl ifconfig.co") con i pulsanti icona 2 "OK" pulsante predefinito 1 con titolo "Il tuo indirizzo IP attuale è .." rinuncia dopo 5 - "curl ifconfig.io" -- alternato
end get_my_IP

su screenCaptureToDesktop ()
    esegui script di shell "/ usr / sbin / screencapture \" "& ¬
        POSIX percorso di (percorso del desktop come stringa) & ¬
        "Screen Shot" & (data corrente) & ".png \" "
end screenCaptureToDesktop
 

UPDATE

SOLUTION 2

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

Penso che questa soluzione sia più promettente della SOLUZIONE 1.

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

in fuga
    eseguire ProgressBar
fine corsa

inattivo
    ritardo 0.2
    attivare
    impostare il pulsante sul pulsante restituito di (visualizza finestra di dialogo ¬
        "La finestra di dialogo di avanzamento dovrebbe essere andata a questo punto." pulsanti {"QUIT", "CONTINUE"} ¬
        pulsante predefinito ¬
        "CONTINUA" con titolo ¬
        "BACKUP UTILITY" con icona 0 ¬
        arrendersi dopo le 10)
    se il pulsante = "QUIT" allora
        smettere
    altrimenti se theButton = "" allora
        smettere
    altrimenti se il pulsante = "CONTINUA" allora
        provare
            eseguire ProgressBar
        fine prova
    finisci se
    ritorno 1
fine inattivo

quando esci
    - Eseguito quando lo script si chiude
    continue quit: consente di chiudere lo script
fine esci

script ProgressBar
    imposta mainFolder per scegliere la cartella con prompt ¬
        "SCEGLI LA TUA CARTELLA SORGENTE PER IL BACKUP"
    imposta backupFolder per scegliere la cartella con prompt ¬
        "SCEGLI LA CARTELLA DELLA DESTINAZIONE DI BACKUP"
    impostare la data su (data corrente) - (14 * giorni)

    dire all'applicazione "Finder"
        imposta allFiles sull'intero contenuto della cartella mainFolder come elenco di alias
    fine raccontare

    impostare ilFileCount per contare di tutti i file

    impostare i passaggi totali di avanzamento suFileCount
    imposta lo stato di avanzamento dei passaggi completati su 0
    imposta la descrizione dell'avanzamento su "Elaborazione file in corso ..."
    imposta una descrizione aggiuntiva dell'avanzamento su "Preparazione all'elaborazione".

    ripetere con theName da 1 a numero di elementi in allFiles
imposta this_item su item theName of allFiles
        dire all'applicazione "Finder"
            duplica this_item in backupFolder ¬
                con sostituzione
        fine raccontare
        imposta la descrizione aggiuntiva dell'avanzamento su ¬
            "File duplicato" & theName & "di" & theFileCount & ¬
            "nella cartella" & backupFolder
        impostare l'avanzamento dei passaggi completati su theName
    fine ripetizione

    - Reimposta le informazioni sullo stato di avanzamento
    imposta i passi totali di avanzamento su 0
    imposta l'avanzamento dei passaggi completati su 0
    imposta la descrizione dell'avanzamento su ""
    imposta la descrizione aggiuntiva dell'avanzamento su ""
fine script
 

enter image description here

Tutti gli altri comandi che desideri eseguire, inseriscili nel gestore Quit prima del comando "continue quit"
Wow, ti do un enorme merito per aver scoperto questa soluzione alternativa.Il tuo metodo risolve davvero la mia domanda.Praticamente implementato nelle mie applicazioni reali, questo metodo ha i suoi limiti.Dato che non c'è modo di uscire dalla subroutine `on quit` una volta entrati, non è più possibile avvolgere l'intero script in un ciclo` repeat`, per esempio.In ogni caso, non credo che troverò una soluzione migliore del tuo metodo!Grazie!
@rubik'ssphere Potrebbe non essere possibile avvolgere l'intero script in un ciclo di ripetizione, ma ho aggiornato il codice per mostrare un esempio di come eseguire alcuni cicli di ripetizione all'interno del gestore di chiusura.Puoi rendere enormi gli altri gestori con i propri loop di ripetizione e subroutine
Soluzione molto interessante.(E ancora una bizzarra decisione di design da parte di Apple.)


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...