Daniel Berger
7/16/2008 12:41:00 AM
Bob Batzinger wrote:
> I have followed the discussion for getting the win32 methods
> Process.create and Process.kill to work that have been posted earlier on
> this forum. In an electronic signage project, I have no trouble getting
> Ruby to create and destroy a process running ruby.exe or notepad.
> However, when I try to use Ruby to open and close a browser application
> like Firefox or a PDF viewer, the following code will open the
> application but the kill method aborts with a error message "The handle
> is invalid." I get this regardless of whether I use the full path name
> of the application or the name without an extension of applications that
> are located within a directory of the system PATH.
>
> require 'rubygems'
> require 'win32/process'
>
> info = Process.create(
> :app_name => '"c:\program files\mozilla firefox\firefox.exe"'
> )
> sleep 5
> Process.kill(9, info.process_id)
>
> This is very baffling to me and I would appreciate any hints or
> suggestions on how to over come this problem. Thanks.
>
> BTW, I am using win32-process-0.5.9 and Ruby 1.8.6. The same results are
> obtained on both Win XP and Windows Vista.
This isn't a problem with win32-process. It's an architectural issue
with applications like Firefox and Adobe Acrobat. If you try another
program like Notepad or Internet Explorer, as you mentioned, it works fine.
When, for example, Firefox starts up it first checks to see if another
instance of Firefox is already running. If it is, it recreates itself as
a remote thread within that process instead, killing the spawned process
almost immediately. So, by the time you try to kill it, it's already
dead and you get an error.
That's my guess anyway, which is based on the fact that, no matter how
many instances of Firefox I startup manually, only one Firefox process
shows up in my Process Explorer.
It's possible to terminate a remote thread within a process on Windows,
but we don't currently provide an interface for that. Perhaps we should
add Process.kill_remote_thread. With that method, users could then do:
# Currently hypothetical
begin
Process.kill(1, info.process_id)
rescue Process::Error => err
if err.to_s == "The handle is invalid"
Process.kill_remote_thread(1, info.thread_id)
end
end
There are other ways you could do this currently, but they require
leaving the process and thread handles open, and then closing them using
native Windows functions via windows-pr.
Regards,
Dan
PS - As a general rule, you should avoid using kill 9 on Windows.
Reserve it for hanging processes only.