/// <summary>
        /// Executes a tool, logs standard error and a nonzero exit code as errors, returns the output and optionally logs that
        /// as well.
        /// </summary>
        /// <param name="log">used for logging</param>
        /// <param name="executable">the name of the executable</param>
        /// <param name="args">the command line arguments</param>
        /// <param name="logOutput">should we log the output in real time</param>
        /// <returns>the output of the tool</returns>
        public static string ExecuteWithLogging(TaskLoggingHelper log, string executable, string args, bool logOutput)
        {
            if (log == null)
            {
                throw new ArgumentNullException("log");
            }

            log.LogMessage(MessageImportance.Low, "Executing tool: {0} {1}", executable, args);

            var exec = new ShellWrapper(executable, args);

            // stderr is logged as errors
            exec.ErrorDataReceived += (sender, e) =>
            {
                if (e.Data != null)
                {
                    log.LogError(e.Data);
                }
            };

            // stdout is logged normally if requested
            if (logOutput)
            {
                exec.OutputDataReceived += (sender, e) =>
                {
                    if (e.Data != null)
                    {
                        log.LogMessage(MessageImportance.Normal, e.Data);
                    }
                };
            }

            // execute the process
            exec.Execute();

            // check the exit code
            if (exec.ExitCode != 0)
            {
                log.LogError("The tool {0} exited with error code {1}", executable, exec.ExitCode);
            }

            return(exec.StandardOutput);
        }
        /// <summary>
        /// Executes a tool, logs standard error and a nonzero exit code as errors, returns the output and optionally logs that
        /// as well.
        /// </summary>
        /// <param name="log">used for logging</param>
        /// <param name="executable">the name of the executable</param>
        /// <param name="args">the command line arguments</param>
        /// <param name="logOutput">should we log the output in real time</param>
        /// <returns>the output of the tool</returns>
        public static string ExecuteWithLogging(TaskLoggingHelper log, string executable, string args, bool logOutput)
        {
            if (log == null)
            {
                throw new ArgumentNullException("log");
            }

            log.LogMessage(MessageImportance.Low, "Executing tool: {0} {1}", executable, args);

            var exec = new ShellWrapper(executable, args);

            // stderr is logged as errors
            exec.ErrorDataReceived += (sender, e) =>
            {
                if (e.Data != null)
                {
                    log.LogError(e.Data);
                }
            };

            // stdout is logged normally if requested
            if (logOutput)
            {
                exec.OutputDataReceived += (sender, e) =>
                {
                    if (e.Data != null)
                    {
                        log.LogMessage(MessageImportance.Normal, e.Data);
                    }
                };
            }

            // execute the process
            exec.Execute();

            // check the exit code
            if (exec.ExitCode != 0)
            {
                log.LogError("The tool {0} exited with error code {1}", executable, exec.ExitCode);
            }

            return exec.StandardOutput;
        }