Ruby: Kill Chrome Process
-
04-12-2019 - |
Question
I'm using WATIR to control browser, but there is page that never fully loads everything stucks. After 60 second timeout WATIR gives me error and I can keep writing commands, but If I try to close the browser with WATIR in made functions everything stucks.
If I close the browser manually everything seems to keep going ok so I'm looking for option to find chrome process id, PID and kill the process using ruby.
Here is code sample I found:
irb
require "watir-webdriver"
proxy = "78.159.102.86:49295"
browser = Watir::Browser.new :chrome, :switches => ['--proxy-server=' + proxy]
bridge = browser.instance_variable_get(:@bridge)
launcher = bridge.instance_variable_get(:@launcher)
binary = launcher.instance_variable_get(:@binary)
process = binary.instance_variable_get(:@process)
process.pid
All this methods gives me NIL. The last one - NoMethodError: undefined method `pid' for nil:NilClass
From my research I think that I need to get PID. Then I can close process.
Any tips? I'm using windows! So far it seems that there are no in made methods for killing process by name in Ruby.
edit:
I found what works from windows command line:
taskkill /im Firefox.exe /f /t >nul 2>&1
But since I'm on ruby it gives me error:
SyntaxError: (irb):1: unknown regexp option - f (irb):1: syntax error, unexpected tINTEGER, expecting keyword_do or '{' or '(' taskkill /im Firefox.exe /f /t >nul 2>&1
How to execute cmd command from ruby?
La solution
I'm not sure system works on windows but give it a try.
system("taskkill /im Firefox.exe /f /t >nul 2>&1")
Autres conseils
You can do this:
a) Get the PID of the Chrome process:
browser_pid = @browser.driver.instance_variable_get(:@bridge).instance_variable_get(:@service).instance_variable_get(:@process).pid
Pass the browser_pid to system kill:
system("taskkill pid #{browser_pid} /f /t >nul 2>&1")
The sample code in the original post combined with @daremkd answer gives us the internal variables for Firefox and Chrome. Putting them together, here's what I'll be using as a watir-webdriver Watir::Browser#pid:
require 'watir-webdriver'
module Watir
class Browser
def pid
if driver.browser == :firefox
[:@bridge, :@launcher, :@binary, :@process, :@pid]
elsif driver.browser == :chrome
[:@bridge, :@service, :@process, :@pid]
else
raise NotImplementedError.new "PID lookup undefined for Watir::Browser :#{driver.browser}"
end.
inject(browser.driver) { |pv, sym| pv.instance_variable_get sym }
end
end
end
Here's the monkey patch used in the context used to close both browsers:
browser = Watir::Browser.new :firefox
pid = browser.pid
`taskkill /pid #{pid}` # browser.close
browser = Watir::Browser.new :chrome
pid = browser.pid
`taskkill /pid #{pid} /f /t` # note the `/t` to kill the spawned tree