Module: Mixlib::ShellOut::Windows
- Includes:
- Process::Constants, Process::Functions
- Included in:
- Mixlib::ShellOut, Utils
- Defined in:
- lib/mixlib/shellout/windows.rb
Defined Under Namespace
Classes: ThingThatLooksSortOfLikeAProcessStatus, Utils
Constant Summary collapse
- TIME_SLICE =
0.05
Constants included from Process::Constants
Process::Constants::ENVIRONMENT_BLOCK_ENDS, Process::Constants::ERROR_LOGON_TYPE_NOT_GRANTED, Process::Constants::ERROR_PRIVILEGE_NOT_HELD, Process::Constants::LOGON32_LOGON_BATCH, Process::Constants::LOGON32_LOGON_INTERACTIVE, Process::Constants::LOGON32_PROVIDER_DEFAULT, Process::Constants::UOI_NAME, Process::Constants::WAIT_ABANDONED, Process::Constants::WAIT_ABANDONED_0, Process::Constants::WAIT_FAILED, Process::Constants::WAIT_OBJECT_0, Process::Constants::WAIT_TIMEOUT, Process::Constants::WIN32_PROFILETYPE_LOCAL, Process::Constants::WIN32_PROFILETYPE_PT_MANDATORY, Process::Constants::WIN32_PROFILETYPE_PT_ROAMING, Process::Constants::WIN32_PROFILETYPE_PT_ROAMING_PREEXISTING, Process::Constants::WIN32_PROFILETYPE_PT_TEMPORARY
Instance Method Summary collapse
-
#run_command ⇒ Object
– Missing lots of features from the UNIX version, such as uid, etc.
-
#validate_options(opts) ⇒ Object
Option validation that is windows specific.
Instance Method Details
#run_command ⇒ Object
– Missing lots of features from the UNIX version, such as uid, etc.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/mixlib/shellout/windows.rb', line 55 def run_command # # Create pipes to capture stdout and stderr, # stdout_read, stdout_write = IO.pipe stderr_read, stderr_write = IO.pipe stdin_read, stdin_write = IO.pipe open_streams = [ stdout_read, stderr_read ] @execution_time = 0 begin # # Set cwd, environment, appname, etc. # app_name, command_line = command_to_run(combine_args(*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 # default to local account database if domain is not specified create_process_args[:domain] = domain.nil? ? "." : domain create_process_args[:with_logon] = with_logon if with_logon create_process_args[:password] = password if password create_process_args[:elevated] = elevated if elevated # # Start the process # process, profile, token = Process.create3(create_process_args) logger&.debug(format_process(process, app_name, command_line, timeout)) begin # Start pushing data into input stdin_write << input if input # Close pipe to kick things off stdin_write.close # # Wait for the process to finish, consuming output as we go # start_wait = Time.now loop do wait_status = WaitForSingleObject(process.process_handle, 0) case wait_status when WAIT_OBJECT_0 # Save the execution time @execution_time = Time.now - start_wait # 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 begin require "wmi-lite/wmi" wmi = WmiLite::Wmi.new kill_process_tree(process.process_id, wmi, logger) Process.kill(:KILL, process.process_id) rescue SystemCallError logger&.warn("Failed to kill timed out process #{process.process_id}") end # Save the execution time @execution_time = Time.now - start_wait raise Mixlib::ShellOut::CommandTimeout, [ "command timed out:", format_for_exception, format_process(process, app_name, command_line, timeout), ].join("\n") 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) if process.thread_handle CloseHandle(process.process_handle) if process.process_handle Process.unload_user_profile(token, profile) if profile CloseHandle(token) if token 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 |
#validate_options(opts) ⇒ Object
Option validation that is windows specific
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/mixlib/shellout/windows.rb', line 34 def (opts) if opts[:user] && !opts[:password] raise InvalidCommandOption, "You must supply a password when supplying a user in windows" end if !opts[:user] && opts[:password] raise InvalidCommandOption, "You must supply a user when supplying a password in windows" end if opts[:elevated] && !opts[:user] && !opts[:password] raise InvalidCommandOption, "`elevated` option should be passed only with `username` and `password`." end if opts[:elevated] && opts[:elevated] != true && opts[:elevated] != false raise InvalidCommandOption, "Invalid value passed for `elevated`. Please provide true/false." end end |