/// <summary>
 /// Returns whether the property contains any sensitive data
 /// </summary>
 public bool ContainsSensitiveData()
 {
     return(ProcessRunnerArguments.ContainsSensitiveData(Id) || ProcessRunnerArguments.ContainsSensitiveData(Value));
 }
예제 #2
0
        /// <summary>
        /// Runs the specified executable and returns a boolean indicating success or failure
        /// </summary>
        /// <remarks>The standard and error output will be streamed to the logger. Child processes do not inherit the env variables from the parent automatically</remarks>
        public bool Execute(ProcessRunnerArguments runnerArgs)
        {
            if (runnerArgs == null)
            {
                throw new ArgumentNullException(nameof(runnerArgs));
            }
            Debug.Assert(!string.IsNullOrWhiteSpace(runnerArgs.ExeName), "Process runner exe name should not be null/empty");

            if (!File.Exists(runnerArgs.ExeName))
            {
                logger.LogError(Resources.ERROR_ProcessRunner_ExeNotFound, runnerArgs.ExeName);
                ExitCode = ErrorCode;
                return(false);
            }

            var psi = new ProcessStartInfo()
            {
                FileName = runnerArgs.ExeName,
                RedirectStandardError  = true,
                RedirectStandardOutput = true,
                UseShellExecute        = false, // required if we want to capture the error output
                ErrorDialog            = false,
                CreateNoWindow         = true,
                Arguments        = runnerArgs.GetEscapedArguments(),
                WorkingDirectory = runnerArgs.WorkingDirectory
            };

            SetEnvironmentVariables(psi, runnerArgs.EnvironmentVariables);

            bool succeeded;

            using (var process = new Process())
            {
                process.StartInfo           = psi;
                process.ErrorDataReceived  += OnErrorDataReceived;
                process.OutputDataReceived += OnOutputDataReceived;

                process.Start();
                process.BeginErrorReadLine();
                process.BeginOutputReadLine();

                // Warning: do not log the raw command line args as they
                // may contain sensitive data
                logger.LogDebug(Resources.MSG_ExecutingFile,
                                runnerArgs.ExeName,
                                runnerArgs.AsLogText(),
                                runnerArgs.WorkingDirectory,
                                runnerArgs.TimeoutInMilliseconds,
                                process.Id);

                succeeded = process.WaitForExit(runnerArgs.TimeoutInMilliseconds);
                if (succeeded)
                {
                    process.WaitForExit(); // Give any asynchronous events the chance to complete
                }

                // false means we asked the process to stop but it didn't.
                // true: we might still have timed out, but the process ended when we asked it to
                if (succeeded)
                {
                    logger.LogDebug(Resources.MSG_ExecutionExitCode, process.ExitCode);
                    ExitCode = process.ExitCode;
                }
                else
                {
                    ExitCode = ErrorCode;

                    try
                    {
                        process.Kill();
                        logger.LogWarning(Resources.WARN_ExecutionTimedOutKilled, runnerArgs.TimeoutInMilliseconds, runnerArgs.ExeName);
                    }
                    catch
                    {
                        logger.LogWarning(Resources.WARN_ExecutionTimedOutNotKilled, runnerArgs.TimeoutInMilliseconds, runnerArgs.ExeName);
                    }
                }

                succeeded = succeeded && (ExitCode == 0);
            }

            return(succeeded);
        }