/// <summary>
        /// Kills all running processes.
        /// </summary>
        public static void KillAll()
        {
            List <IProcess> ProcessesToKill = new List <IProcess>();

            lock (SyncObject)
            {
                foreach (var ProcResult in ActiveProcesses)
                {
                    if (!ProcResult.HasExited)
                    {
                        ProcessesToKill.Add(ProcResult);
                    }
                }
                ActiveProcesses.Clear();
            }
            // Remove processes that can't be killed
            for (int ProcessIndex = ProcessesToKill.Count - 1; ProcessIndex >= 0; --ProcessIndex)
            {
                var ProcessName = ProcessesToKill[ProcessIndex].GetProcessName();
                if (!String.IsNullOrEmpty(ProcessName) && !CanBeKilled(ProcessName))
                {
                    CommandUtils.LogLog("Ignoring process \"{0}\" because it can't be killed.", ProcessName);
                    ProcessesToKill.RemoveAt(ProcessIndex);
                }
            }
            if (ProcessesToKill.Count > 0)
            {
                CommandUtils.LogLog("Trying to kill {0} spawned processes.", ProcessesToKill.Count);
                foreach (var Proc in ProcessesToKill)
                {
                    CommandUtils.LogLog("  {0}", Proc.GetProcessName());
                }
                if (CommandUtils.IsBuildMachine)
                {
                    for (int Cnt = 0; Cnt < 9; Cnt++)
                    {
                        bool AllDone = true;
                        foreach (var Proc in ProcessesToKill)
                        {
                            try
                            {
                                if (!Proc.HasExited)
                                {
                                    AllDone = false;
                                    CommandUtils.LogLog("Waiting for process: {0}", Proc.GetProcessName());
                                }
                            }
                            catch (Exception)
                            {
                                CommandUtils.LogWarning("Exception Waiting for process");
                                AllDone = false;
                            }
                        }
                        try
                        {
                            if (ProcessResult.HasAnyDescendants(Process.GetCurrentProcess()))
                            {
                                AllDone = false;
                                CommandUtils.Log("Waiting for descendants of main process...");
                            }
                        }
                        catch (Exception Ex)
                        {
                            CommandUtils.LogWarning("Exception Waiting for descendants of main process. " + Ex);
                            AllDone = false;
                        }

                        if (AllDone)
                        {
                            break;
                        }
                        Thread.Sleep(10000);
                    }
                }
                foreach (var Proc in ProcessesToKill)
                {
                    var ProcName = Proc.GetProcessName();
                    try
                    {
                        if (!Proc.HasExited)
                        {
                            CommandUtils.LogLog("Killing process: {0}", ProcName);
                            Proc.StopProcess(false);
                        }
                    }
                    catch (Exception Ex)
                    {
                        CommandUtils.LogWarning("Exception while trying to kill process {0}:", ProcName);
                        CommandUtils.LogWarning(LogUtils.FormatException(Ex));
                    }
                }
                try
                {
                    if (CommandUtils.IsBuildMachine && ProcessResult.HasAnyDescendants(Process.GetCurrentProcess()))
                    {
                        CommandUtils.LogLog("current process still has descendants, trying to kill them...");
                        ProcessResult.KillAllDescendants(Process.GetCurrentProcess());
                    }
                }
                catch (Exception)
                {
                    CommandUtils.LogWarning("Exception killing descendants of main process");
                }
            }
        }
 /// <summary>
 /// Wraps an action in an exception block.
 /// Ensures individual actions can be performed and exceptions won't prevent further actions from being executed.
 /// Useful for shutdown code where shutdown may be in several stages and it's important that all stages get a chance to run.
 /// </summary>
 /// <param name="Action"></param>
 private static void NoThrow(System.Action Action, string ActionDesc)
 {
     try
     {
         Action();
     }
     catch (Exception Ex)
     {
         Log.TraceError("Exception performing nothrow action \"{0}\": {1}", ActionDesc, LogUtils.FormatException(Ex));
     }
 }
Exemple #3
0
 public void WriteLine(string Source, TraceEventType Verbosity, string Message)
 {
     Message = LogUtils.FormatMessage(Source, Verbosity, Message);
     WriteToFile(Message);
 }
Exemple #4
0
        /// <summary>
        /// Runs a commandlet using Engine/Binaries/Win64/UE4Editor-Cmd.exe.
        /// </summary>
        /// <param name="ProjectFile">Project name.</param>
        /// <param name="UE4Exe">The name of the UE4 Editor executable to use.</param>
        /// <param name="Commandlet">Commandlet name.</param>
        /// <param name="Parameters">Command line parameters (without -run=)</param>
        public static void RunCommandlet(FileReference ProjectName, string UE4Exe, string Commandlet, string Parameters = null)
        {
            Log("Running UE4Editor {0} for project {1}", Commandlet, ProjectName);

            var CWD = Path.GetDirectoryName(UE4Exe);

            string EditorExe = UE4Exe;

            if (String.IsNullOrEmpty(CWD))
            {
                EditorExe = HostPlatform.Current.GetUE4ExePath(UE4Exe);
                CWD       = CombinePaths(CmdEnv.LocalRoot, HostPlatform.Current.RelativeBinariesFolder);
            }

            PushDir(CWD);

            DateTime StartTime = DateTime.UtcNow;

            string LocalLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.EngineSavedFolder, Commandlet));

            Log("Commandlet log file is {0}", LocalLogFile);
            string Args = String.Format(
                "{0} -run={1} {2} -abslog={3} -stdout -CrashForUAT -unattended {5}{4}",
                (ProjectName == null) ? "" : CommandUtils.MakePathSafeToUseWithCommandLine(ProjectName.FullName),
                Commandlet,
                String.IsNullOrEmpty(Parameters) ? "" : Parameters,
                CommandUtils.MakePathSafeToUseWithCommandLine(LocalLogFile),
                IsBuildMachine ? "-buildmachine" : "",
                (GlobalCommandLine.Verbose || GlobalCommandLine.AllowStdOutLogVerbosity) ? "-AllowStdOutLogVerbosity " : ""
                );
            ERunOptions Opts = ERunOptions.Default;

            if (GlobalCommandLine.UTF8Output)
            {
                Args += " -UTF8Output";
                Opts |= ERunOptions.UTF8Output;
            }
            var RunResult = Run(EditorExe, Args, Options: Opts, Identifier: Commandlet);

            PopDir();

            // If we're running on a Mac, dump all the *.crash files that were generated while the editor was running.
            if (HostPlatform.Current.HostEditorPlatform == UnrealTargetPlatform.Mac)
            {
                // If the exit code indicates the main process crashed, introduce a small delay because the crash report is written asynchronously.
                // If we exited normally, still check without waiting in case SCW or some other child process crashed.
                if (RunResult.ExitCode > 128)
                {
                    CommandUtils.Log("Pausing before checking for crash logs...");
                    Thread.Sleep(10 * 1000);
                }

                // Create a list of directories containing crash logs, and add the system log folder
                List <string> CrashDirs = new List <string>();
                CrashDirs.Add("/Library/Logs/DiagnosticReports");

                // Add the user's log directory too
                string HomeDir = Environment.GetEnvironmentVariable("HOME");
                if (!String.IsNullOrEmpty(HomeDir))
                {
                    CrashDirs.Add(Path.Combine(HomeDir, "Library/Logs/DiagnosticReports"));
                }

                // Check each directory for crash logs
                List <FileInfo> CrashFileInfos = new List <FileInfo>();
                foreach (string CrashDir in CrashDirs)
                {
                    try
                    {
                        DirectoryInfo CrashDirInfo = new DirectoryInfo(CrashDir);
                        if (CrashDirInfo.Exists)
                        {
                            CrashFileInfos.AddRange(CrashDirInfo.EnumerateFiles("*.crash", SearchOption.TopDirectoryOnly).Where(x => x.LastWriteTimeUtc >= StartTime));
                        }
                    }
                    catch (UnauthorizedAccessException)
                    {
                        // Not all account types can access /Library/Logs/DiagnosticReports
                    }
                }

                // Dump them all to the log
                foreach (FileInfo CrashFileInfo in CrashFileInfos)
                {
                    // snmpd seems to often crash (suspect due to it being starved of CPU cycles during cooks)
                    if (!CrashFileInfo.Name.StartsWith("snmpd_"))
                    {
                        CommandUtils.Log("Found crash log - {0}", CrashFileInfo.FullName);
                        try
                        {
                            string[] Lines = File.ReadAllLines(CrashFileInfo.FullName);
                            foreach (string Line in Lines)
                            {
                                CommandUtils.Log("Crash: {0}", Line);
                            }
                        }
                        catch (Exception Ex)
                        {
                            CommandUtils.LogWarning("Failed to read file ({0})", Ex.Message);
                        }
                    }
                }
            }

            // Copy the local commandlet log to the destination folder.
            string DestLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.LogFolder, Commandlet));

            if (!CommandUtils.CopyFile_NoExceptions(LocalLogFile, DestLogFile))
            {
                CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, LocalLogFile, DestLogFile);
            }
            string ProjectStatsDirectory = CombinePaths((ProjectName == null)? CombinePaths(CmdEnv.LocalRoot, "Engine") : Path.GetDirectoryName(ProjectName.FullName), "Saved", "Stats");

            if (Directory.Exists(ProjectStatsDirectory))
            {
                string DestCookerStats = CmdEnv.LogFolder;
                foreach (var StatsFile in Directory.EnumerateFiles(ProjectStatsDirectory, "*.csv"))
                {
                    if (!CommandUtils.CopyFile_NoExceptions(StatsFile, CombinePaths(DestCookerStats, Path.GetFileName(StatsFile))))
                    {
                        CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, StatsFile, CombinePaths(DestCookerStats, Path.GetFileName(StatsFile)));
                    }
                }
            }
//			else
//			{
//				CommandUtils.LogWarning("Failed to find directory {0} will not save stats", ProjectStatsDirectory);
//			}

            // Whether it was copied correctly or not, delete the local log as it was only a temporary file.
            CommandUtils.DeleteFile_NoExceptions(LocalLogFile);

            // Throw an exception if the execution failed. Draw attention to signal exit codes on Posix systems, rather than just printing the exit code
            if (RunResult.ExitCode != 0)
            {
                string ExitCodeDesc = "";
                if (RunResult.ExitCode > 128 && RunResult.ExitCode < 128 + 32)
                {
                    if (RunResult.ExitCode == 139)
                    {
                        ExitCodeDesc = " (segmentation fault)";
                    }
                    else
                    {
                        ExitCodeDesc = String.Format(" (signal {0})", RunResult.ExitCode - 128);
                    }
                }
                throw new CommandletException(DestLogFile, RunResult.ExitCode, "Editor terminated with exit code {0}{1} while running {2}{3}; see log {4}", RunResult.ExitCode, ExitCodeDesc, Commandlet, (ProjectName == null)? "" : String.Format(" for {0}", ProjectName), DestLogFile);
            }
        }
Exemple #5
0
        /// <summary>
        /// Copies a file.
        /// </summary>
        /// <param name="SourceName">Source name</param>
        /// <param name="TargetName">Target name</param>
        /// <returns>True if the operation was successful, false otherwise.</returns>
        public static bool SafeCopyFile(string SourceName, string TargetName, bool bQuiet = false)
        {
            if (!bQuiet)
            {
                Log.WriteLine(TraceEventType.Information, "SafeCopyFile {0} {1}", SourceName, TargetName);
            }
            const int MaxAttempts = 10;
            int       Attempts    = 0;

            bool Result = true;

            do
            {
                Result = true;
                bool Retry = true;
                try
                {
                    File.Copy(SourceName, TargetName, overwrite: true);
                    Retry = !File.Exists(TargetName);
                    if (!Retry)
                    {
                        FileInfo SourceInfo = new FileInfo(SourceName);
                        FileInfo TargetInfo = new FileInfo(TargetName);
                        if (SourceInfo.Length != TargetInfo.Length)
                        {
                            Log.WriteLine(TraceEventType.Warning, "Size mismatch {0} = {1} to {2} = {3}", SourceName, SourceInfo.Length, TargetName, TargetInfo.Length);
                            Retry = true;
                        }
                        if (!((SourceInfo.LastWriteTimeUtc - TargetInfo.LastWriteTimeUtc).TotalSeconds < 1 && (SourceInfo.LastWriteTimeUtc - TargetInfo.LastWriteTimeUtc).TotalSeconds > -1))
                        {
                            Log.WriteLine(TraceEventType.Warning, "Date mismatch {0} = {1} to {2} = {3}", SourceName, SourceInfo.LastWriteTimeUtc, TargetName, TargetInfo.LastWriteTimeUtc);
                            Retry = true;
                        }
                    }
                }
                catch (Exception Ex)
                {
                    Log.WriteLine(System.Diagnostics.TraceEventType.Warning, "SafeCopyFile Exception was {0}", LogUtils.FormatException(Ex));
                    Retry = true;
                }

                if (Retry)
                {
                    if (Attempts + 1 < MaxAttempts)
                    {
                        Log.WriteLine(TraceEventType.Warning, "Failed to copy {0} to {1}, deleting, waiting 10s and retrying.", SourceName, TargetName);
                        if (File.Exists(TargetName))
                        {
                            SafeDeleteFile(TargetName);
                        }
                        Thread.Sleep(10000);
                    }
                    else
                    {
                        Log.WriteLine(TraceEventType.Warning, "Failed to copy {0} to {1}", SourceName, TargetName);
                    }
                    Result = false;
                }
            }           while (Result == false && ++Attempts < MaxAttempts);

            return(Result);
        }
Exemple #6
0
        public void WriteLine(string Source, TraceEventType Verbosity, string Format, params object[] Args)
        {
            var Message = LogUtils.FormatMessage(Source, Verbosity, Format, Args);

            WriteToFile(Message);
        }
Exemple #7
0
        /// <summary>
        /// Copies a file.
        /// </summary>
        /// <param name="SourceName">Source name</param>
        /// <param name="TargetName">Target name</param>
        /// <returns>True if the operation was successful, false otherwise.</returns>
        public static bool SafeCopyFile(string SourceName, string TargetName, bool bQuiet = false, bool bFilterSpecialLinesFromIniFiles = false)
        {
            if (!bQuiet)
            {
                Log.TraceLog("SafeCopyFile {0} {1}", SourceName, TargetName);
            }
            const int MaxAttempts = 10;
            int       Attempts    = 0;

            bool Result = true;

            do
            {
                Result = true;
                bool Retry = true;
                try
                {
                    bool bSkipSizeCheck = false;
                    if (bFilterSpecialLinesFromIniFiles && Path.GetExtension(SourceName) == ".ini")
                    {
                        FilterIniFile(SourceName, TargetName);
                        // ini files may change size, don't check
                        bSkipSizeCheck = true;
                    }
                    else
                    {
                        if (File.Exists(SourceName))
                        {
                            File.Copy(SourceName, TargetName, overwrite: true);
                        }
                        else
                        {
                            Log.TraceWarning("Skip copying file {0} because it doesn't exist.", SourceName);
                        }
                    }
                    Retry = !File.Exists(TargetName);
                    if (!Retry)
                    {
                        FileInfo SourceInfo = new FileInfo(SourceName);
                        FileInfo TargetInfo = new FileInfo(TargetName);
                        if (!bSkipSizeCheck && SourceInfo.Length != TargetInfo.Length)
                        {
                            Log.TraceWarning("Size mismatch {0} = {1} to {2} = {3}", SourceName, SourceInfo.Length, TargetName, TargetInfo.Length);
                            Retry = true;
                        }
                        // Timestamps should be no more than 2 seconds out - assuming this as exFAT filesystems store timestamps at 2 second intervals:
                        // http://ntfs.com/exfat-time-stamp.htm
                        if (!((SourceInfo.LastWriteTimeUtc - TargetInfo.LastWriteTimeUtc).TotalSeconds < 2 && (SourceInfo.LastWriteTimeUtc - TargetInfo.LastWriteTimeUtc).TotalSeconds > -2))
                        {
                            Log.TraceWarning("Date mismatch {0} = {1} to {2} = {3}", SourceName, SourceInfo.LastWriteTimeUtc, TargetName, TargetInfo.LastWriteTimeUtc);
                            Retry = true;
                        }
                    }
                }
                catch (Exception Ex)
                {
                    Log.TraceWarning("SafeCopyFile Exception was {0}", LogUtils.FormatException(Ex));
                    Retry = true;
                }

                if (Retry)
                {
                    if (Attempts + 1 < MaxAttempts)
                    {
                        Log.TraceWarning("Failed to copy {0} to {1}, deleting, waiting 10s and retrying.", SourceName, TargetName);
                        if (File.Exists(TargetName))
                        {
                            SafeDeleteFile(TargetName);
                        }
                        Thread.Sleep(10000);
                    }
                    else
                    {
                        Log.TraceWarning("Failed to copy {0} to {1}", SourceName, TargetName);
                    }
                    Result = false;
                }
            }while (Result == false && ++Attempts < MaxAttempts);

            return(Result);
        }
Exemple #8
0
        public static int Main()
        {
            var CommandLine = SharedUtils.ParseCommandLine();

            LogUtils.InitLogging(CommandLine);

            ExitCode ReturnCode = ExitCode.Success;

            try
            {
                // ensure we can resolve any external assemblies as necessary.
                AssemblyUtils.InstallAssemblyResolver(Path.GetDirectoryName(Assembly.GetEntryAssembly().GetOriginalLocation()));
                HostPlatform.Initialize();

                Log.TraceVerbose("{2}: Running on {0} as a {1}-bit process.", HostPlatform.Current.GetType().Name, Environment.Is64BitProcess ? 64 : 32, DateTime.UtcNow.ToString("o"));

                XmlConfigLoader.Init();

                // Log if we're running from the launcher
                var ExecutingAssemblyLocation = Assembly.GetExecutingAssembly().Location;
                if (string.Compare(ExecutingAssemblyLocation, Assembly.GetEntryAssembly().GetOriginalLocation(), StringComparison.OrdinalIgnoreCase) != 0)
                {
                    Log.TraceVerbose("Executed from AutomationToolLauncher ({0})", ExecutingAssemblyLocation);
                }
                Log.TraceVerbose("CWD={0}", Environment.CurrentDirectory);

                // Hook up exit callbacks
                var Domain = AppDomain.CurrentDomain;
                Domain.ProcessExit  += Domain_ProcessExit;
                Domain.DomainUnload += Domain_ProcessExit;
                HostPlatform.Current.SetConsoleCtrlHandler(CtrlHandlerDelegateInstance);

                var Version = AssemblyUtils.ExecutableVersion;
                Log.TraceVerbose("{0} ver. {1}", Version.ProductName, Version.ProductVersion);

                // Don't allow simultaneous execution of AT (in the same branch)
                ReturnCode = InternalUtils.RunSingleInstance(MainProc, CommandLine);
            }
            catch (AutomationException Ex)
            {
                Log.TraceError("AutomationTool terminated with exception: {0}", Ex);
                ReturnCode = Ex.ErrorCode;
            }
            catch (Exception Ex)
            {
                // Catch all exceptions and propagate the ErrorCode if we are given one.
                Log.TraceError("AutomationTool terminated with exception: {0}", Ex);
                ReturnCode = ExitCode.Error_Unknown;
            }
            finally
            {
                // In all cases, do necessary shut down stuff, but don't let any additional exceptions leak out while trying to shut down.

                // Make sure there's no directories on the stack.
                NoThrow(() => CommandUtils.ClearDirStack(), "Clear Dir Stack");

                // Try to kill process before app domain exits to leave the other KillAll call to extreme edge cases
                NoThrow(() => { if (ShouldKillProcesses && !Utils.IsRunningOnMono)
                                {
                                    ProcessManager.KillAll();
                                }
                        }, "Kill All Processes");

                Log.TraceInformation("AutomationTool exiting with ExitCode={0} ({1})", (int)ReturnCode, ReturnCode);

                // Can't use NoThrow here because the code logs exceptions. We're shutting down logging!
                LogUtils.ShutdownLogging();
            }

            // STOP: No code beyond the return statement should go beyond this point!
            // Nothing should happen after the finally block above is finished.
            return((int)ReturnCode);
        }
Exemple #9
0
        /// <summary>
        /// Main method.
        /// </summary>
        /// <param name="Arguments">Command line</param>
        public static ExitCode Process(string[] Arguments, StartupTraceListener StartupListener)
        {
            // Initial check for local or build machine runs BEFORE we parse the command line (We need this value set
            // in case something throws the exception while parsing the command line)
            IsBuildMachine = !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("uebp_LOCAL_ROOT")) || Arguments.Any(x => x.Equals("-BuildMachine", StringComparison.InvariantCultureIgnoreCase));

            // Scan the command line for commands to execute.
            var    CommandsToExecute = new List <CommandInfo>();
            string OutScriptsForProjectFileName;
            var    AdditionalScriptsFolders = new List <string>();

            ParseCommandLine(Arguments, CommandsToExecute, out OutScriptsForProjectFileName, AdditionalScriptsFolders);

            // Get the path to the telemetry file, if present
            string TelemetryFile = CommandUtils.ParseParamValue(Arguments, "-Telemetry");

            Log.TraceVerbose("IsBuildMachine={0}", IsBuildMachine);
            Environment.SetEnvironmentVariable("IsBuildMachine", IsBuildMachine ? "1" : "0");

            // should we kill processes on exit
            ShouldKillProcesses = !GlobalCommandLine.NoKill;
            Log.TraceVerbose("ShouldKillProcesses={0}", ShouldKillProcesses);

            if (CommandsToExecute.Count == 0 && GlobalCommandLine.Help)
            {
                DisplayHelp();
                return(ExitCode.Success);
            }

            // Disable AutoSDKs if specified on the command line
            if (GlobalCommandLine.NoAutoSDK)
            {
                PlatformExports.PreventAutoSDKSwitching();
            }

            // Setup environment
            Log.TraceLog("Setting up command environment.");
            CommandUtils.InitCommandEnvironment();

            // Create the log file, and flush the startup listener to it
            TraceListener LogTraceListener = LogUtils.AddLogFileListener(CommandUtils.CmdEnv.LogFolder, CommandUtils.CmdEnv.FinalLogFolder);

            StartupListener.CopyTo(LogTraceListener);
            Trace.Listeners.Remove(StartupListener);

            // Initialize UBT
            if (!UnrealBuildTool.PlatformExports.Initialize())
            {
                Log.TraceInformation("Failed to initialize UBT");
                return(ExitCode.Error_Unknown);
            }

            // Clean rules folders up
            ProjectUtils.CleanupFolders();

            // Compile scripts.
            Compiler = new ScriptCompiler();
            using (TelemetryStopwatch ScriptCompileStopwatch = new TelemetryStopwatch("ScriptCompile"))
            {
                Compiler.FindAndCompileAllScripts(OutScriptsForProjectFileName, AdditionalScriptsFolders);
            }

            if (GlobalCommandLine.CompileOnly)
            {
                Log.TraceInformation("Compilation successful, exiting (CompileOnly)");
                return(ExitCode.Success);
            }

            if (GlobalCommandLine.List)
            {
                ListAvailableCommands(Compiler.Commands);
                return(ExitCode.Success);
            }

            if (GlobalCommandLine.Help)
            {
                DisplayHelp(CommandsToExecute, Compiler.Commands);
                return(ExitCode.Success);
            }

            // Enable or disable P4 support
            CommandUtils.InitP4Support(CommandsToExecute, Compiler.Commands);
            if (CommandUtils.P4Enabled)
            {
                Log.TraceLog("Setting up Perforce environment.");
                CommandUtils.InitP4Environment();
                CommandUtils.InitDefaultP4Connection();
            }

            // Find and execute commands.
            ExitCode Result = Execute(CommandsToExecute, Compiler.Commands);

            if (TelemetryFile != null)
            {
                Directory.CreateDirectory(Path.GetDirectoryName(TelemetryFile));
                CommandUtils.Telemetry.Write(TelemetryFile);
            }
            return(Result);
        }
Exemple #10
0
        /// <summary>
        /// Runs a commandlet using Engine/Binaries/Win64/UE4Editor-Cmd.exe.
        /// </summary>
        /// <param name="ProjectName">Project name.</param>
        /// <param name="UE4Exe">The name of the UE4 Editor executable to use.</param>
        /// <param name="Commandlet">Commandlet name.</param>
        /// <param name="Parameters">Command line parameters (without -run=)</param>
        public static void RunCommandlet(string ProjectName, string UE4Exe, string Commandlet, string Parameters = null)
        {
            Log("Running UE4Editor {0} for project {1}", Commandlet, ProjectName);

            var CWD = Path.GetDirectoryName(UE4Exe);

            string EditorExe = UE4Exe;

            if (String.IsNullOrEmpty(CWD))
            {
                EditorExe = HostPlatform.Current.GetUE4ExePath(UE4Exe);
                CWD       = CombinePaths(CmdEnv.LocalRoot, HostPlatform.Current.RelativeBinariesFolder);
            }

            PushDir(CWD);

            string LocalLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.EngineSavedFolder, Commandlet));

            Log("Commandlet log file is {0}", LocalLogFile);
            string Args = String.Format(
                "{0} -run={1} {2} -abslog={3} -stdout -FORCELOGFLUSH -CrashForUAT -unattended {5}{4}",
                (ProjectName == null) ? "" : CommandUtils.MakePathSafeToUseWithCommandLine(ProjectName),
                Commandlet,
                String.IsNullOrEmpty(Parameters) ? "" : Parameters,
                CommandUtils.MakePathSafeToUseWithCommandLine(LocalLogFile),
                IsBuildMachine ? "-buildmachine" : "",
                GlobalCommandLine.Verbose ? "-AllowStdOutLogVerbosity" : ""
                );
            ERunOptions Opts = ERunOptions.Default;

            if (GlobalCommandLine.UTF8Output)
            {
                Args += " -UTF8Output";
                Opts |= ERunOptions.UTF8Output;
            }
            var RunResult = Run(EditorExe, Args, Options: Opts);

            PopDir();

            // Draw attention to signal exit codes on Posix systems, rather than just printing the exit code
            if (RunResult.ExitCode > 128 && RunResult.ExitCode < 128 + 32)
            {
                if (RunResult.ExitCode == 139)
                {
                    CommandUtils.LogError("Editor terminated abnormally due to a segmentation fault");
                }
                else
                {
                    CommandUtils.LogError("Editor terminated abnormally with signal {0}", RunResult.ExitCode - 128);
                }
            }

            // Copy the local commandlet log to the destination folder.
            string DestLogFile = LogUtils.GetUniqueLogName(CombinePaths(CmdEnv.LogFolder, Commandlet));

            if (!CommandUtils.CopyFile_NoExceptions(LocalLogFile, DestLogFile))
            {
                CommandUtils.LogWarning("Commandlet {0} failed to copy the local log file from {1} to {2}. The log file will be lost.", Commandlet, LocalLogFile, DestLogFile);
            }

            // Whether it was copied correctly or not, delete the local log as it was only a temporary file.
            CommandUtils.DeleteFile_NoExceptions(LocalLogFile);

            if (RunResult.ExitCode != 0)
            {
                throw new AutomationException("BUILD FAILED: Failed while running {0} for {1}; see log {2}", Commandlet, ProjectName, DestLogFile);
            }
        }
Exemple #11
0
        public static int Main()
        {
            var CommandLine = SharedUtils.ParseCommandLine();

            HostPlatform.Initialize();

            LogUtils.InitLogging(CommandLine);
            Log.WriteLine(TraceEventType.Information, "Running on {0}", HostPlatform.Current.GetType().Name);

            XmlConfigLoader.Init();

            // Log if we're running from the launcher
            var ExecutingAssemblyLocation = CommandUtils.CombinePaths(Assembly.GetExecutingAssembly().Location);

            if (String.Compare(ExecutingAssemblyLocation, CommandUtils.CombinePaths(InternalUtils.ExecutingAssemblyLocation), true) != 0)
            {
                Log.WriteLine(TraceEventType.Information, "Executed from AutomationToolLauncher ({0})", ExecutingAssemblyLocation);
            }
            Log.WriteLine(TraceEventType.Information, "CWD={0}", Environment.CurrentDirectory);

            // Hook up exit callbacks
            var Domain = AppDomain.CurrentDomain;

            Domain.ProcessExit  += Domain_ProcessExit;
            Domain.DomainUnload += Domain_ProcessExit;
            HostPlatform.Current.SetConsoleCtrlHandler(ProgramCtrlHandler);

            var Version = InternalUtils.ExecutableVersion;

            Log.WriteLine(TraceEventType.Verbose, "{0} ver. {1}", Version.ProductName, Version.ProductVersion);

            try
            {
                // Don't allow simultaneous execution of AT (in the same branch)
                ReturnCode = InternalUtils.RunSingleInstance(MainProc, CommandLine);
            }
            catch (Exception Ex)
            {
                Log.WriteLine(TraceEventType.Error, "AutomationTool terminated with exception:");
                Log.WriteLine(TraceEventType.Error, LogUtils.FormatException(Ex));
                Log.WriteLine(TraceEventType.Error, Ex.Message);
                if (ReturnCode == 0)
                {
                    ReturnCode = (int)ErrorCodes.Error_Unknown;
                }
            }

            // Make sure there's no directiories on the stack.
            CommandUtils.ClearDirStack();
            Environment.ExitCode = ReturnCode;

            // Try to kill process before app domain exits to leave the other KillAll call to extreme edge cases
            if (ShouldKillProcesses)
            {
                ProcessManager.KillAll();
            }

            Log.WriteLine(TraceEventType.Information, "AutomationTool exiting with ExitCode={0}", ReturnCode);
            LogUtils.CloseFileLogging();

            return(ReturnCode);
        }