Here's one for the Win32 gurus out there.
I'm trying to make a timed system command under Windows that sends a
CONTROL-C (^C) to the program that it spawns after a specified amount of
time has passed. Here's the code I have now:
######################start of code################3
require 'Win32API'
require 'timeout'
CREATE_NEW_CONSOLE = 0x10
CREATE_NEW_PROCESS_GROUP = 0x00000200
DETACHED_PROCESS = 0x08
WAIT_TIMEOUT = 0x102
CTRL_C_EVENT = 0
CreateProcess =
Win32API.new("kernel32","CreateProcess",['L','P','L','L','L','L','L','L','P','P'],'L')
GetExitCodeProcess =
Win32API.new("kernel32","GetExitCodeProcess",['L','P'],'L')
WaitForSingleObject =
Win32API.new("kernel32","WaitForSingleObject",['L','L'],'L')
TerminateProcess =
Win32API.new("kernel32","TerminateProcess",['L','L'],'L')
CloseHandle = Win32API.new("kernel32","CloseHandle",['L'],'L')
GenerateConsoleCtrlEvent =
Win32API.new("kernel32","GenerateConsoleCtrlEvent",['L','L'],'L')
def timedSystemCommand( command, redirFile, time=100 )
puts "command is: #{command}\n"
fputc = Win32API.new("crtdll","fputc", ['L','L'],'L')
killed = 0
exitcode = "\0" * 32
si = [68].pack("L") + "\0" * 64
pi = "\0" * 16;
######
if redirFile
tmpfile = File.new("tmp","w")
save_stdout = $stdout.clone
$stdout.reopen(tmpfile)
end
CreateProcess.Call(0,"#{command}",0,0,1,CREATE_NEW_PROCESS_GROUP,0,0,si,pi)
hProcess = pi.unpack("LLLL")[0]
hThread = pi.unpack("LLLL")[1]
dwProcessId = pi.unpack("LLLL")[2]
dwThreadId = pi.unpack("LLLL")[3]
a = WaitForSingleObject.Call( hProcess, time*1000 )
if a==WAIT_TIMEOUT
puts "got a timeout error"
puts "send ^C!"
GenerateConsoleCtrlEvent.Call(CTRL_C_EVENT, dwProcessId )
killed = 1
end
GetExitCodeProcess.Call(hProcess, exitcode)
exitcode = exitcode.unpack("L")
CloseHandle.Call(hProcess)
if redirFile
$stdout.reopen(save_stdout)
end
save_stdout.close if save_stdout
return killed, exitcode
end
#########################end of code############################
On Windows 98 the above code works fine. Under Windows NT and 2000,
however, the program gets launched and the timeout condition happens, but
the CTRL_C_EVENT that is supposed to be sent by GenerateConsoleCtrlEvent
is never received (or sent, maybe?) so the application continues on it's
merry way and is not killed.
WinNT/2000 should be able to handle all of these functions OK - could it
be a problem with Cygwin?. I also tried a C version of the above (a C
Ruby extension) and got the same results on NT (again I was using Cygwin
to compile).
Phil