def run_command
stdout_read, stdout_write = IO.pipe
stderr_read, stderr_write = IO.pipe
stdin_read, stdin_write = IO.pipe
open_streams = [ stdout_read, stderr_read ]
begin
app_name, command_line = command_to_run(self.command)
create_process_args = {
:app_name => app_name,
:command_line => command_line,
:startup_info => {
:stdout => stdout_write,
:stderr => stderr_write,
:stdin => stdin_read
},
:environment => inherit_environment.map { |k,v| "#{k}=#{v}" },
:close_handles => false
}
create_process_args[:cwd] = cwd if cwd
process = Process.create(create_process_args)
begin
stdin_write << input if input
stdin_write.close
start_wait = Time.now
while true
wait_status = WaitForSingleObject(process.process_handle, 0)
case wait_status
when WAIT_OBJECT_0
exit_code = [0].pack('l')
unless GetExitCodeProcess(process.process_handle, exit_code)
raise get_last_error
end
@status = ThingThatLooksSortOfLikeAProcessStatus.new
@status.exitstatus = exit_code.unpack('l').first
return self
when WAIT_TIMEOUT
if (Time.now - start_wait) > timeout
raise Mixlib::ShellOut::CommandTimeout, "command timed out:\n#{format_for_exception}"
end
consume_output(open_streams, stdout_read, stderr_read)
else
raise "Unknown response from WaitForSingleObject(#{process.process_handle}, #{timeout*1000}): #{wait_status}"
end
end
ensure
CloseHandle(process.thread_handle)
CloseHandle(process.process_handle)
end
ensure
stdout_write.close
stderr_write.close
while consume_output(open_streams, stdout_read, stderr_read)
end
end
end