module Mixlib::ShellOut::Windows
def command_to_run
def command_to_run if command =~ SHOULD_USE_CMD [ ENV['COMSPEC'], "cmd /c #{command}" ] else [ which(command[0,command.index(/\s/) || command.length]), command ] end end
def consume_output(open_streams, stdout_read, stderr_read)
def consume_output(open_streams, stdout_read, stderr_read) return false if open_streams.length == 0 ready = IO.select(open_streams, nil, nil, READ_WAIT_TIME) return true if ! ready if ready.first.include?(stdout_read) begin next_chunk = stdout_read.readpartial(READ_SIZE) @stdout << next_chunk @live_stream << next_chunk if @live_stream rescue EOFError stdout_read.close open_streams.delete(stdout_read) end end if ready.first.include?(stderr_read) begin @stderr << stderr_read.readpartial(READ_SIZE) rescue EOFError stderr_read.close open_streams.delete(stderr_read) end end return true end
def inherit_environment
def inherit_environment result = {} ENV.each_pair do |k,v| result[k] = v end environment.each_pair do |k,v| if v == nil result.delete(k) else result[k] = v end end result end
def run_command
Missing lots of features from the UNIX version, such as
--
def run_command # # Create pipes to capture stdout and stderr, # stdout_read, stdout_write = IO.pipe stderr_read, stderr_write = IO.pipe open_streams = [ stdout_read, stderr_read ] begin # # Set cwd, environment, appname, etc. # app_name, command_line = command_to_run create_process_args = { :app_name => app_name, :command_line => command_line, :startup_info => { :stdout => stdout_write, :stderr => stderr_write }, :environment => inherit_environment.map { |k,v| "#{k}=#{v}" }, :close_handles => false } create_process_args[:cwd] = cwd if cwd # # Start the process # process = Process.create(create_process_args) begin # # Wait for the process to finish, consuming output as we go # start_wait = Time.now while true wait_status = WaitForSingleObject(process.process_handle, 0) case wait_status when WAIT_OBJECT_0 # Get process exit code 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 # Kill the process 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 # # Consume all remaining data from the pipes until they are closed # stdout_write.close stderr_write.close while consume_output(open_streams, stdout_read, stderr_read) end end end
def which(cmd)
def which(cmd) return cmd if File.executable? cmd exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') + [''] : [''] ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| exts.each { |ext| exe = "#{path}/#{cmd}#{ext}" return exe if File.executable? exe } end return nil end