Killing Threads & Processes on Windows

x = Thread.new { system("c:/program files/internet explorer/iexplore.exe") }
x.alive # Works

why doesnt x.kill actually "kill" internet explorer? When I think of
kill, I think of "gone" as in *nix gone.

Yet in Windows, I get:
irb(main):004:0> x.kill
=> #<Thread:0x2cfd680 dead>
irb(main):005:0>

---and IE remains.

x = IO.popen("c:/program files/internet explorer/iexplore.exe")
x.close

--Just hangs until IE is manually closed.

From a to z, how can this be done?

If another module is needed, can it be installed via gems? Thanks guys.

Hi,

At Wed, 19 Oct 2005 07:44:35 +0900,
x1 wrote in [ruby-talk:161230]:

x = Thread.new { system("c:/program files/internet explorer/iexplore.exe") }
x.alive # Works

why doesnt x.kill actually "kill" internet explorer? When I think of
kill, I think of "gone" as in *nix gone.

A thread and a process spawned within it are not related.

x = IO.popen("c:/program files/internet explorer/iexplore.exe")
x.close

IO#close try to send a signal to the process, however, the
problem is no signal mechanism across processes on Windows,
unless the target has a console.

···

--
Nobu Nakada

You might want to take a look at Daniel Berger's win32/process package
on RAA - http://raa.ruby-lang.org/project/win32-process/

Sean

Thank you for the response.

I did find a hack using wscript that id like to share:

x = IO.popen("c:/program files/internet explorer/iexplore.exe")
x.pid
=> 3672
system("wscript.exe test.vbs")

I know this is a hack but can win32api not be used to make a ruby
implementation of this?
------------------------test.vbs--------------------
strComputer = "."
Set objWMIService = GetObject _
    ("winmgmts:\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery _
    ("Select * from Win32_Process Where ProcessID = 3672")
For Each objProcess in colProcessList
    objProcess.Terminate()
Next
-----------------------/test.vbs----------------------------

Thx again!!

···

On 10/18/05, nobu.nokada@softhome.net <nobu.nokada@softhome.net> wrote:

Hi,

At Wed, 19 Oct 2005 07:44:35 +0900,
x1 wrote in [ruby-talk:161230]:
> x = Thread.new { system("c:/program files/internet explorer/iexplore.exe") }
> x.alive # Works
>
> why doesnt x.kill actually "kill" internet explorer? When I think of
> kill, I think of "gone" as in *nix gone.

A thread and a process spawned within it are not related.

> x = IO.popen("c:/program files/internet explorer/iexplore.exe")
> x.close

IO#close try to send a signal to the process, however, the
problem is no signal mechanism across processes on Windows,
unless the target has a console.

--
Nobu Nakada

Nobu wrote:

IO#close try to send a signal to the process, however, the
problem is no signal mechanism across processes on Windows,
unless the target has a console.

Could IO#close use ExitProcess() on Windows?

OP wrote:

If another module is needed, can it be installed
via gems? Thanks guys.

win32-process will probably do what you need:
http://rubyforge.org/projects/win32utils

I don't believe you can get that via gem.

There may be an easier way, depending on what you're trying to do. For
example, if you just want Internet Explorer, you can use its COM
interface:

require 'win32ole'
ie = WIN32OLE.new("InternetExplorer.Application")
ie.visible = true
sleep 1
ie.quit

Cheers,
Dave

You can write the WMI script in Ruby:

require 'win32ole'
strComputer = "."
objWMIService = WIN32OLE.connect \
    ("winmgmts:\\#{strComputer}\root\cimv2")
colProcessList = objWMIService.ExecQuery \
    ("Select * from Win32_Process Where ProcessID = 3672")
colProcessList.each do |objProcess|
    objProcess.Terminate()
end

Cheers,
Dave

or you can use a combination of sysinternals' pslist, and pskill. i
find it handy for those systems where wscript and cscript have been
disabled (like on my own w2k system)

···

x1 wrote on 10/18/2005 9:30 PM:

system("wscript.exe test.vbs")

--
http://home.cogeco.ca/~tsummerfelt1
telnet://ventedspleen.dyndns.org

You can do WMI in Ruby. There's a library already built for this.

Warren Seltzer

P.S. Have you ever seen such a hellacious mess as WMI?

Dave, that my friend was EXACTLY what I wanted. Thank you!!!

Sean, I'll check that out also. Thanks again!

···

On 10/18/05, dave.burt@gmail.com <dave.burt@gmail.com> wrote:

You can write the WMI script in Ruby:

require 'win32ole'
strComputer = "."
objWMIService = WIN32OLE.connect \
    ("winmgmts:\\#{strComputer}\root\cimv2")
colProcessList = objWMIService.ExecQuery \
    ("Select * from Win32_Process Where ProcessID = 3672")
colProcessList.each do |objProcess|
    objProcess.Terminate()
end

Cheers,
Dave

Hi,

At Wed, 19 Oct 2005 11:16:57 +0900,
dave.burt@gmail.com wrote in [ruby-talk:161280]:

You can write the WMI script in Ruby:

require 'win32ole'
strComputer = "."
objWMIService = WIN32OLE.connect \
    ("winmgmts:\\#{strComputer}\root\cimv2")
colProcessList = objWMIService.ExecQuery \
    ("Select * from Win32_Process Where ProcessID = 3672")
colProcessList.each do |objProcess|
    objProcess.Terminate()
end

Does it work on Win9X?

···

--
Nobu Nakada

for future reference to others and thanks to dave.

There was a small issue with backslashes and escapes in the example
dave gave us....

Very small prob but.. wanted to inform others who may stumble on this..

Here's what worked for me in the end:
require 'win32ole'

def start_process(command)
  return IO.popen(command).pid
end

def kill_process(pid)
  strComputer = "."
  objWMIService = WIN32OLE.connect \
     ("winmgmts:\\\\#{strComputer}\\root\\cimv2")
  colProcessList = objWMIService.ExecQuery \
     ("Select * from Win32_Process Where ProcessID = #{x.to_s}")
  colProcessList.each do |objProcess|
     objProcess.Terminate()
  end
  return "done"
end

command = "c:/program files/internet explorer/iexplore.exe"
pid = start_process(command)
puts "killing pid now (#{pid}).."
sleep 1 #probably not needed
puts kill_process(pid)

···

On 10/27/05, Warren Seltzer <warrens@actcom.net.il> wrote:

You can do WMI in Ruby. There's a library already built for this.

Warren Seltzer

P.S. Have you ever seen such a hellacious mess as WMI?

nobuyoshi nakada wrote:

Hi,

At Wed, 19 Oct 2005 11:16:57 +0900,
dave.burt@gmail.com wrote in [ruby-talk:161280]:
> You can write the WMI script in Ruby:
>
> require 'win32ole'
> strComputer = "."
> objWMIService = WIN32OLE.connect \
> ("winmgmts:\\#{strComputer}\root\cimv2")
> colProcessList = objWMIService.ExecQuery \
> ("Select * from Win32_Process Where ProcessID = 3672")
> colProcessList.each do |objProcess|
> objProcess.Terminate()
> end

Does it work on Win9X?

No, I don't think so -- I think all of WMI is WinNT family only, but
this is a direct translation of the VBScript given.

If you're asking about my suggestion of using TerminateProcess() as an
alternative to signals to close a popen'd process in IO#close, then the
answer is yes. (TerminateProcess(), not ExitProcess() which kills the
calling process.)

Documentation for TerminateProcess():

Cheers,
Dave

whoops..

replace x.to_s with pid.to_s in the kill method..
ProcessID = #{pid.to_s}"

···

On 11/9/05, x1 <caldridge@gmail.com> wrote:

for future reference to others and thanks to dave.

There was a small issue with backslashes and escapes in the example
dave gave us....

Very small prob but.. wanted to inform others who may stumble on this..

Here's what worked for me in the end:
require 'win32ole'

def start_process(command)
        return IO.popen(command).pid
end

def kill_process(pid)
        strComputer = "."
        objWMIService = WIN32OLE.connect \
           ("winmgmts:\\\\#{strComputer}\\root\\cimv2")
        colProcessList = objWMIService.ExecQuery \
           ("Select * from Win32_Process Where ProcessID = #{x.to_s}")
        colProcessList.each do |objProcess|
           objProcess.Terminate()
        end
        return "done"
end

command = "c:/program files/internet explorer/iexplore.exe"
pid = start_process(command)
puts "killing pid now (#{pid}).."
sleep 1 #probably not needed
puts kill_process(pid)

On 10/27/05, Warren Seltzer <warrens@actcom.net.il> wrote:
> You can do WMI in Ruby. There's a library already built for this.
>
> Warren Seltzer
>
> P.S. Have you ever seen such a hellacious mess as WMI?
>
>
>
>

Hi,

At Wed, 19 Oct 2005 17:11:58 +0900,
dave.burt@gmail.com wrote in [ruby-talk:161338]:

If you're asking about my suggestion of using TerminateProcess() as an
alternative to signals to close a popen'd process in IO#close, then the
answer is yes. (TerminateProcess(), not ExitProcess() which kills the
calling process.)

I know about TerminateProcess(), but think it is considered
critical for general purpose, like as SIGKILL.

···

--
Nobu Nakada

dave.burt... wrote:

nobuyoshi nakada wrote:
> Hi,
>
> At Wed, 19 Oct 2005 11:16:57 +0900,
> dave.burt... wrote in [ruby-talk:161280]:
> > You can write the WMI script in Ruby:
> >
> > require 'win32ole'
> > strComputer = "."
> > objWMIService = WIN32OLE.connect \
> > ("winmgmts:\\#{strComputer}\root\cimv2")
> > colProcessList = objWMIService.ExecQuery \
> > ("Select * from Win32_Process Where ProcessID = 3672")
> > colProcessList.each do |objProcess|
> > objProcess.Terminate()
> > end
>
> Does it work on Win9X?

No, I don't think so -- [...]

True - needs WMI core 1.5 add-on -- see Run-Time Requirements here:

I wanted to point out, though, that passing a Ruby string
to WIN32OLE.connect means those '\' must be doubled:

":\\\\.\\root\\cimv2"
# 000 3a 5c 5c 2e 5c 72 6f 6f 74 5c 63 69 6d 76 32 :\\.\root\cimv2

.... rather than ...

":\\.\root\cimv2"
# 000 3a 5c 2e 0d 6f 6f 74 09 6d 76 32 :\..oot.mv2

Alternatively, '/' appears to be accepted by WMI:
"winmgmts://./root/cimv2"

daz

nobu nakada wrote:

I know about TerminateProcess(), but think it is considered
critical for general purpose, like as SIGKILL.

You're probably right, it is severe, but rb_waitpid shouldn't return with
the process still running, should it?

Cheers,
Dave