Use AppleScript to check if GUI apps are running.

This commit is contained in:
Markus Reiter 2019-09-15 01:08:04 +02:00
parent 2c0d25da6f
commit d8afed206f
2 changed files with 33 additions and 12 deletions

View File

@ -127,7 +127,7 @@ module Cask
# :quit/:signal must come before :kext so the kext will not be in use by a running process # :quit/:signal must come before :kext so the kext will not be in use by a running process
def uninstall_quit(*bundle_ids, command: nil, **_) def uninstall_quit(*bundle_ids, command: nil, **_)
bundle_ids.each do |bundle_id| bundle_ids.each do |bundle_id|
next if running_processes(bundle_id).empty? next unless running?(bundle_id)
unless User.current.gui? unless User.current.gui?
opoo "Not logged into a GUI; skipping quitting application ID '#{bundle_id}'." opoo "Not logged into a GUI; skipping quitting application ID '#{bundle_id}'."
@ -146,10 +146,10 @@ module Cask
Kernel.loop do Kernel.loop do
next unless quit(bundle_id).success? next unless quit(bundle_id).success?
if running_processes(bundle_id).empty? next if running?(bundle_id)
puts "Application '#{bundle_id}' quit successfully."
break puts "Application '#{bundle_id}' quit successfully."
end break
end end
end end
rescue Timeout::Error rescue Timeout::Error
@ -159,6 +159,28 @@ module Cask
end end
end end
def running?(bundle_id)
script = <<~JAVASCRIPT
'use strict';
ObjC.import('stdlib')
function run(argv) {
try {
var app = Application(argv[0])
if (app.running()) {
$.exit(0)
}
} catch (err) { }
$.exit(1)
}
JAVASCRIPT
system_command("osascript", args: ["-l", "JavaScript", "-e", script, bundle_id],
print_stderr: true).status.success?
end
def quit(bundle_id) def quit(bundle_id)
script = <<~JAVASCRIPT script = <<~JAVASCRIPT
'use strict'; 'use strict';
@ -181,8 +203,7 @@ module Cask
JAVASCRIPT JAVASCRIPT
system_command "osascript", args: ["-l", "JavaScript", "-e", script, bundle_id], system_command "osascript", args: ["-l", "JavaScript", "-e", script, bundle_id],
print_stderr: false, print_stderr: false
sudo: true
end end
private :quit private :quit

View File

@ -119,7 +119,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
it "is skipped when the user does not have automation access" do it "is skipped when the user does not have automation access" do
allow(User).to receive(:automation_access?).and_return false allow(User).to receive(:automation_access?).and_return false
allow(User.current).to receive(:gui?).and_return true allow(User.current).to receive(:gui?).and_return true
allow(subject).to receive(:running_processes).with(bundle_id).and_return([[0, "", bundle_id]]) allow(subject).to receive(:running?).with(bundle_id).and_return(true)
expect { expect {
subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command)
@ -128,7 +128,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
it "is skipped when the user is not a GUI user" do it "is skipped when the user is not a GUI user" do
allow(User.current).to receive(:gui?).and_return false allow(User.current).to receive(:gui?).and_return false
allow(subject).to receive(:running_processes).with(bundle_id).and_return([[0, "", bundle_id]]) allow(subject).to receive(:running?).with(bundle_id).and_return(true)
expect { expect {
subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command)
@ -139,10 +139,10 @@ shared_examples "#uninstall_phase or #zap_phase" do
allow(User).to receive(:automation_access?).and_return true allow(User).to receive(:automation_access?).and_return true
allow(User.current).to receive(:gui?).and_return true allow(User.current).to receive(:gui?).and_return true
expect(subject).to receive(:running_processes).with(bundle_id).ordered.and_return([[0, "", bundle_id]]) expect(subject).to receive(:running?).with(bundle_id).ordered.and_return(true)
expect(subject).to receive(:quit).with(bundle_id) expect(subject).to receive(:quit).with(bundle_id)
.and_return(instance_double("SystemCommand::Result", success?: true)) .and_return(instance_double("SystemCommand::Result", success?: true))
expect(subject).to receive(:running_processes).with(bundle_id).ordered.and_return([]) expect(subject).to receive(:running?).with(bundle_id).ordered.and_return(false)
expect { expect {
subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command) subject.public_send(:"#{artifact_dsl_key}_phase", command: fake_system_command)
@ -153,7 +153,7 @@ shared_examples "#uninstall_phase or #zap_phase" do
allow(User).to receive(:automation_access?).and_return true allow(User).to receive(:automation_access?).and_return true
allow(User.current).to receive(:gui?).and_return true allow(User.current).to receive(:gui?).and_return true
allow(subject).to receive(:running_processes).with(bundle_id).and_return([[0, "", bundle_id]]) allow(subject).to receive(:running?).with(bundle_id).and_return(true)
allow(subject).to receive(:quit).with(bundle_id) allow(subject).to receive(:quit).with(bundle_id)
.and_return(instance_double("SystemCommand::Result", success?: false)) .and_return(instance_double("SystemCommand::Result", success?: false))