Ich habe ein kleines Dienstskript geschrieben, um ein iTerm-Terminalfenster in einem beliebigen Ordner im Finder zu öffnen.
Ich möchte, dass überprüft wird, ob iTerm ausgeführt wird und ob die Terminalsitzung in einem neuen Tab statt in einem vorhandenen geöffnet wird.
Das Skript geht so:
on run {input, parameters}
set cdPath to "cd " & (quoted form of POSIX path of (input as string))
if application "iTerm" is running then
display notification "running"
tell application "iTerm"
set termWin to (current terminal)
tell termWin
launch session "Default"
tell the last session
write text cdPath
end tell
end tell
end tell
else
display notification "not running"
tell application "iTerm"
activate
set termWin2 to (current terminal)
tell termWin2
tell the last session
write text cdPath
end tell
end tell
end tell
end if
return input
end run
Das Problem ist, dass, wenn ich das Skript als Dienst ausführe, es sich immer so verhält, als ob iTerm bereits ausgeführt würde (es wird die Benachrichtigung "Ausgeführt" angezeigt), selbst wenn iTerm geschlossen ist und ganz klar NICHT ausgeführt wird.
Aber wenn ich dasselbe Skript in den Skripteditor einfüge (cdPath auf ein Literal, wie set cdPath to "cd /etc"
) und es direkt ausführe, funktioniert es korrekt, indem ich entweder eine neue iTerm-Instanz öffne oder eine vorhandene wiederverwende und eine neue Registerkarte erstelle und das entsprechende zeige Benachrichtigungen.
Was ist denn hier los? Warum würde das Ausführen des Skripts als Dienst erkennen, dass die Anwendung ausgeführt wird, egal was passiert?
Aktualisieren
Wenn ich das Skript vereinfache, um nur die Benachrichtigungen wie folgt anzuzeigen:
on run {input, parameters}
set cdPath to "cd " & (quoted form of POSIX path of (input as string))
if application "iTerm" is running then
display notification "running"
else
display notification "not running"
end if
return input
end run
Es verhält sich wie erwartet (es wird entsprechend „running“ oder „not running“ angezeigt).
Aber wenn ich den Teil "Tell Application" hinzufüge, wird er immer den durchgehenden "Running"-Zweig durchlaufen, egal was passiert.
Z.B:
on run {input, parameters}
set cdPath to "cd " & (quoted form of POSIX path of (input as string))
if application "iTerm" is running then
display notification "running"
else
display notification "not running"
tell application "iTerm"
activate
end tell
end if
return input
end run
Öffnet immer iTerm (selbst wenn es tell application "iTerm"
sich im Zweig "nicht läuft" befindet, aber die Benachrichtigung "wird ausgeführt" aus dem Zweig "wird ausgeführt" anzeigen ... Das bloße Vorhandensein einer "Tell-Anwendung" löst dann das Öffnen der App aus Der Dienst wird ausgeführt.
Gibt es eine Möglichkeit, dies zu umgehen?
Danke und Grüße.
Die Sicherheitsbeschränkungen von El-Capitans sind NICHT für das oben genannte fehlerhafte Verhalten verantwortlich. Ich habe das Skript noch etwas getestet und folgendes festgestellt:
In jweaks-Code bei Stapelüberlauf ist iTerm nur direkt in der 2. Klausel ("tell ...") betroffen .
tell application "System Events" to set theProcesses to name of every ¬
every process whose visible is true
if theProcesses contains "iTerm" then display notification "running"
else [...]
Probieren Sie diesen Code im ScriptEditor, Automator und als Dienst in Safari aus:
display notification "" & running of application "TextEdit"
tell application "TextEdit" to activate
quit application "TextEdit"
display notification "" & running of application "TextEdit"
Sie erhalten unterschiedliche Ergebnisse von AppleScript/Automator (=> false + true ) und Safari ( true + true ). Besonders das True
von AppleScript/Automator aus der 2. Benachrichtigung ist ziemlich aufschlussreich. ... wenn Sie jedoch nur eine Minute Verzögerung einfügen, z. B. 0,01, nach der Zeile "quit", wird die Ausführung als "false" getestet - wenn das Skript von AppleScript/Automator aus ausgeführt wird.
Manchmal habe ich dieses Verhalten auch beim Ausführen von Skripten bemerkt, es ist seltsam. Obwohl es meistens nicht passiert, wenn das Skript nicht über den Skripteditor ausgeführt wird. Hier ist jedoch eine bessere Alternative:
tell application "System Events"
# Adding tell application block has no effect on the if condition
# Try it with TextEdit, that's what I using to try this code, and works fine.
if (the name of application processes as text) contains "iTerm" then
# Will quit the application if running
log "Running"
tell application "iTerm" to quit
else
# Will launch the application otherwise.
log "Not Running"
tell application "iTerm" to activate
end if
end tell
Ich habe gerade einen Weg gefunden, es zu tun. Obwohl ich eine Anwendung anstelle eines Dienstes erstelle, sind sie fast gleich. Die Grundidee besteht darin, es tell application iTerm
in ein anderes Skript oder in Anführungszeichen zu setzen, sodass der Optimierungsprozess es nicht dazu bringt, iTerm zu öffnen, bevor dieses Skript ausgeführt wird. So erhalten Sie das tatsächliche Ergebnis von if application "iTerm" is running
.
Aber in dem zitierten Skript, da es einen tell application
Teil gibt, wissen wir bereits, dass iTerm vor allem geöffnet wird, wir können direkt activate
iTerm und verwenden current session of current terminal
(tatsächlich funktioniert dies sogar in Automator, auch wenn iTerm nicht zuerst geöffnet wird). Ich bin mir nicht sicher, ob delay 0.01
dies hier erforderlich ist (Sie können es auf Ihrem Computer testen). Aber dieser funktioniert für meinen Zweck, nämlich den aktuellen Finder-Pfad in einem neuen iTerm-Fenster auf dem aktuellen Desktop zu öffnen. Und wenn iTerm nicht läuft, werden keine zwei iTerm-Fenster geöffnet.
Lass mich wissen was du denkst. :-)
on run {input, parameters}
tell application "Finder"
set dir_path to quoted form of (POSIX path of (folder of the front window as alias))
end tell
CD_to(dir_path)
end run
on CD_to(theDir)
if application "iTerm" is running then
#display dialog "Running" # for debug
run script "
on run {q}
tell application \":Applications:iTerm.app\"
set term to (make new terminal) # make a new window in current desktop since I don't want to mess with current ones
tell term
launch session \"Default\"
set sesh to current session
end tell
tell sesh
write text \"cd \" & q & \";clear;\"
end tell
activate
end tell
end run
" with parameters {theDir}
else
#display dialog "Not Running" # for debug
run script "
on run {q}
tell application \":Applications:iTerm.app\"
delay 0.01
activate
set sesh to current session of current terminal
tell sesh
write text \"cd \" & q & \";clear;\"
end tell
end tell
end run
" with parameters {theDir}
end if
end CD_to
# part of code comes from http://peterdowns.com/posts/open-iterm-finder-service.html
astroboylrx