/// <summary>
        /// Runs external program.
        /// </summary>
        /// <param name="App">Program filename.</param>
        /// <param name="CommandLine">Commandline</param>
        /// <param name="Input">Optional Input for the program (will be provided as stdin)</param>
        /// <param name="Options">Defines the options how to run. See ERunOptions.</param>
        /// <param name="Env">Environment to pass to program.</param>
        /// <param name="FilterCallback">Callback to filter log spew before output.</param>
        /// <returns>Object containing the exit code of the program as well as it's stdout output.</returns>
        public static IProcessResult Run(string App, string CommandLine = null, string Input = null, ERunOptions Options = ERunOptions.Default, Dictionary <string, string> Env = null, ProcessResult.SpewFilterCallbackType SpewFilterCallback = null)
        {
            App = ConvertSeparators(PathSeparator.Default, App);

            // Get the log name before allowing the platform to modify the app/command-line. We want mono apps to be written to a log named after the application and appear with the application prefix rather than "mono:".
            string LogName = Path.GetFileNameWithoutExtension(App);

            HostPlatform.Current.SetupOptionsForRun(ref App, ref Options, ref CommandLine);
            if (App == "ectool" || App == "zip" || App == "xcodebuild")
            {
                Options &= ~ERunOptions.AppMustExist;
            }

            // Check if the application exists, including the PATH directories.
            if (Options.HasFlag(ERunOptions.AppMustExist) && !FileExists(Options.HasFlag(ERunOptions.NoLoggingOfRunCommand) ? true : false, App))
            {
                bool bExistsInPath = false;
                if (!App.Contains(Path.DirectorySeparatorChar) && !App.Contains(Path.AltDirectorySeparatorChar))
                {
                    string[] PathDirectories = Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator);
                    foreach (string PathDirectory in PathDirectories)
                    {
                        string TryApp = Path.Combine(PathDirectory, App);
                        if (FileExists(Options.HasFlag(ERunOptions.NoLoggingOfRunCommand), TryApp))
                        {
                            App           = TryApp;
                            bExistsInPath = true;
                            break;
                        }
                    }
                }
                if (!bExistsInPath)
                {
                    throw new AutomationException("BUILD FAILED: Couldn't find the executable to Run: {0}", App);
                }
            }
            var StartTime = DateTime.UtcNow;

            UnrealBuildTool.LogEventType SpewVerbosity = Options.HasFlag(ERunOptions.SpewIsVerbose) ? UnrealBuildTool.LogEventType.Verbose : UnrealBuildTool.LogEventType.Console;
            if (!Options.HasFlag(ERunOptions.NoLoggingOfRunCommand))
            {
                LogWithVerbosity(SpewVerbosity, "Run: " + App + " " + (String.IsNullOrEmpty(CommandLine) ? "" : CommandLine));
            }
            IProcessResult Result = ProcessManager.CreateProcess(App, Options.HasFlag(ERunOptions.AllowSpew), LogName, Env, SpewVerbosity: SpewVerbosity, SpewFilterCallback: SpewFilterCallback);
            Process        Proc   = Result.ProcessObject;

            bool bRedirectStdOut = (Options & ERunOptions.NoStdOutRedirect) != ERunOptions.NoStdOutRedirect;

            Proc.StartInfo.FileName        = App;
            Proc.StartInfo.Arguments       = String.IsNullOrEmpty(CommandLine) ? "" : CommandLine;
            Proc.StartInfo.UseShellExecute = false;
            if (bRedirectStdOut)
            {
                Proc.StartInfo.RedirectStandardOutput = true;
                Proc.StartInfo.RedirectStandardError  = true;
                Proc.OutputDataReceived += Result.StdOut;
                Proc.ErrorDataReceived  += Result.StdErr;
            }
            Proc.StartInfo.RedirectStandardInput = Input != null;
            Proc.StartInfo.CreateNoWindow        = true;
            if ((Options & ERunOptions.UTF8Output) == ERunOptions.UTF8Output)
            {
                Proc.StartInfo.StandardOutputEncoding = new System.Text.UTF8Encoding(false, false);
            }
            Proc.Start();

            if (bRedirectStdOut)
            {
                Proc.BeginOutputReadLine();
                Proc.BeginErrorReadLine();
            }

            if (String.IsNullOrEmpty(Input) == false)
            {
                Proc.StandardInput.WriteLine(Input);
                Proc.StandardInput.Close();
            }

            if (!Options.HasFlag(ERunOptions.NoWaitForExit))
            {
                Result.WaitForExit();
                var BuildDuration = (DateTime.UtcNow - StartTime).TotalMilliseconds;
                AddRunTime(App, (int)(BuildDuration));
                Result.ExitCode = Proc.ExitCode;
                if (!Options.HasFlag(ERunOptions.NoLoggingOfRunCommand) || Options.HasFlag(ERunOptions.LoggingOfRunDuration))
                {
                    LogWithVerbosity(SpewVerbosity, "Run: Took {0}s to run {1}, ExitCode={2}", BuildDuration / 1000, Path.GetFileName(App), Result.ExitCode);
                }
                Result.OnProcessExited();
                Result.DisposeProcess();
            }
            else
            {
                Result.ExitCode = -1;
            }

            return(Result);
        }
예제 #2
0
        /// <summary>
        /// Runs external program.
        /// </summary>
        /// <param name="App">Program filename.</param>
        /// <param name="CommandLine">Commandline</param>
        /// <param name="Input">Optional Input for the program (will be provided as stdin)</param>
        /// <param name="Options">Defines the options how to run. See ERunOptions.</param>
        /// <param name="Env">Environment to pass to program.</param>
        /// <param name="FilterCallback">Callback to filter log spew before output.</param>
        /// <returns>Object containing the exit code of the program as well as it's stdout output.</returns>
        public static IProcessResult Run(string App, string CommandLine = null, string Input = null, ERunOptions Options = ERunOptions.Default, Dictionary <string, string> Env = null, ProcessResult.SpewFilterCallbackType SpewFilterCallback = null, string Identifier = null)
        {
            App = ConvertSeparators(PathSeparator.Default, App);

            HostPlatform.Current.SetupOptionsForRun(ref App, ref Options, ref CommandLine);
            if (App == "ectool" || App == "zip" || App == "xcodebuild")
            {
                Options &= ~ERunOptions.AppMustExist;
            }

            // Check if the application exists, including the PATH directories.
            if (Options.HasFlag(ERunOptions.AppMustExist) && !FileExists(Options.HasFlag(ERunOptions.NoLoggingOfRunCommand) ? true : false, App))
            {
                string ResolvedPath = WhichApp(App);

                if (string.IsNullOrEmpty(ResolvedPath))
                {
                    throw new AutomationException("BUILD FAILED: Couldn't find the executable to run: {0}", App);
                }

                App = ResolvedPath;
            }
            var StartTime = DateTime.UtcNow;

            LogEventType SpewVerbosity = Options.HasFlag(ERunOptions.SpewIsVerbose) ? LogEventType.Verbose : LogEventType.Console;

            if (!Options.HasFlag(ERunOptions.NoLoggingOfRunCommand))
            {
                LogWithVerbosity(SpewVerbosity, "Running: " + App + " " + (String.IsNullOrEmpty(CommandLine) ? "" : CommandLine));
            }

            string PrevIndent = null;

            if (Options.HasFlag(ERunOptions.AllowSpew))
            {
                PrevIndent = Tools.DotNETCommon.Log.Indent;
                Tools.DotNETCommon.Log.Indent += "  ";
            }

            IProcessResult Result = ProcessManager.CreateProcess(App, Options.HasFlag(ERunOptions.AllowSpew), !Options.HasFlag(ERunOptions.NoStdOutCapture), Env, SpewVerbosity: SpewVerbosity, SpewFilterCallback: SpewFilterCallback);

            try
            {
                Process Proc = Result.ProcessObject;

                bool bRedirectStdOut = (Options & ERunOptions.NoStdOutRedirect) != ERunOptions.NoStdOutRedirect;
                Proc.StartInfo.FileName        = App;
                Proc.StartInfo.Arguments       = String.IsNullOrEmpty(CommandLine) ? "" : CommandLine;
                Proc.StartInfo.UseShellExecute = false;
                if (bRedirectStdOut)
                {
                    Proc.StartInfo.RedirectStandardOutput = true;
                    Proc.StartInfo.RedirectStandardError  = true;
                    Proc.OutputDataReceived += Result.StdOut;
                    Proc.ErrorDataReceived  += Result.StdErr;
                }
                Proc.StartInfo.RedirectStandardInput = Input != null;
                Proc.StartInfo.CreateNoWindow        = (Options & ERunOptions.NoHideWindow) == 0;
                if ((Options & ERunOptions.UTF8Output) == ERunOptions.UTF8Output)
                {
                    Proc.StartInfo.StandardOutputEncoding = new System.Text.UTF8Encoding(false, false);
                }
                Proc.Start();

                if (bRedirectStdOut)
                {
                    Proc.BeginOutputReadLine();
                    Proc.BeginErrorReadLine();
                }

                if (String.IsNullOrEmpty(Input) == false)
                {
                    Proc.StandardInput.WriteLine(Input);
                    Proc.StandardInput.Close();
                }

                if (!Options.HasFlag(ERunOptions.NoWaitForExit))
                {
                    Result.WaitForExit();
                }
                else
                {
                    Result.ExitCode = -1;
                }
            }
            finally
            {
                if (PrevIndent != null)
                {
                    Tools.DotNETCommon.Log.Indent = PrevIndent;
                }
            }

            if (!Options.HasFlag(ERunOptions.NoWaitForExit))
            {
                var BuildDuration = (DateTime.UtcNow - StartTime).TotalMilliseconds;
                //AddRunTime(App, (int)(BuildDuration));
                Result.ExitCode = Result.ProcessObject.ExitCode;
                if (!Options.HasFlag(ERunOptions.NoLoggingOfRunCommand) || Options.HasFlag(ERunOptions.LoggingOfRunDuration))
                {
                    LogWithVerbosity(SpewVerbosity, "Took {0}s to run {1}, ExitCode={2}", BuildDuration / 1000, Path.GetFileName(App), Result.ExitCode);
                }
                Result.OnProcessExited();
                Result.DisposeProcess();
            }

            return(Result);
        }