/// <summary> /// Renames/moves a file. /// </summary> /// <param name="OldName">Old name</param> /// <param name="NewName">New name</param> /// <returns>True if the operation was successful, false otherwise.</returns> public static bool SafeRenameFile(string OldName, string NewName, bool bQuiet = false) { if (!bQuiet) { Log.TraceLog("SafeRenameFile {0} {1}", OldName, NewName); } const int MaxAttempts = 10; int Attempts = 0; bool Result = true; do { Result = true; try { if (File.Exists(OldName)) { FileAttributes Attributes = File.GetAttributes(OldName); if ((Attributes & FileAttributes.ReadOnly) != 0) { File.SetAttributes(OldName, Attributes & ~FileAttributes.ReadOnly); } } File.Move(OldName, NewName); } catch (Exception Ex) { if (File.Exists(OldName) == true || File.Exists(NewName) == false) { Log.TraceWarning("Failed to rename {0} to {1}", OldName, NewName); Log.TraceWarning(LogUtils.FormatException(Ex)); Result = false; } } }while (Result == false && ++Attempts < MaxAttempts); return(Result); }
/// <summary> /// Kills all child processes of the specified process. /// </summary> /// <param name="ProcessId">Process id</param> public static void KillAllDescendants(Process ProcessToKill) { bool bKilledAChild; do { bKilledAChild = false; // For some reason Process.GetProcesses() sometimes returns the same process twice // So keep track of all processes we already tried to kill var KilledPids = new HashSet <int>(); var AllProcs = Process.GetProcesses(); foreach (Process KillCandidate in AllProcs) { var VisitedPids = new HashSet <int>(); if (ProcessManager.CanBeKilled(KillCandidate.ProcessName) && !KilledPids.Contains(KillCandidate.Id) && IsOurDescendant(ProcessToKill, KillCandidate.Id, VisitedPids)) { KilledPids.Add(KillCandidate.Id); CommandUtils.LogLog("Trying to kill descendant pid={0}, name={1}", KillCandidate.Id, KillCandidate.ProcessName); try { KillCandidate.Kill(); bKilledAChild = true; } catch (Exception Ex) { if (!KillCandidate.HasExited) { CommandUtils.LogWarning("Failed to kill descendant:"); CommandUtils.LogWarning(LogUtils.FormatException(Ex)); } } break; // exit the loop as who knows what else died, so let's get processes anew } } } while (bKilledAChild); }
/// <summary> /// Creates the TraceListener used for file logging. /// We cannot simply use a TextWriterTraceListener because we need more flexibility when the file cannot be created. /// TextWriterTraceListener lazily creates the file, silently failing when it cannot. /// </summary> /// <returns>The newly created TraceListener, or null if it could not be created.</returns> private static TraceListener CreateLogFileListener(out string LogFilename) { StreamWriter LogFile = null; const int MaxAttempts = 10; int Attempt = 0; var TempLogFolder = Path.GetTempPath(); do { if (Attempt == 0) { LogFilename = CommandUtils.CombinePaths(TempLogFolder, "Log.txt"); } else { LogFilename = CommandUtils.CombinePaths(TempLogFolder, String.Format("Log_{0}.txt", Attempt)); } try { // We do not need to set AutoFlush on the StreamWriter because we set Trace.AutoFlush, which calls it for us. // Not only would this be redundant, StreamWriter AutoFlush does not flush the encoder, while a direct call to // StreamWriter.Flush() will, which is what the Trace system with AutoFlush = true will do. // Internally, FileStream constructor opens the file with good arguments for writing to log files. return(new TextWriterTraceListener(new StreamWriter(LogFilename), "AutomationFileLogListener")); } catch (Exception Ex) { if (Attempt == (MaxAttempts - 1)) { // Clear out the LogFilename to indicate we were not able to write one. LogFilename = null; UnrealBuildTool.Log.TraceWarning("Unable to create log file: {0}", LogFilename); UnrealBuildTool.Log.TraceWarning(LogUtils.FormatException(Ex)); } } } while (LogFile == null && ++Attempt < MaxAttempts); return(null); }
public void SaveStatus(BuildNode NodeToDo, string Suffix, string NodeStoreName, bool bSaveSharedTempStorage, string GameNameIfAny, string JobStepIDForFailure = null) { string Contents = "Just a status record: " + Suffix; if (!String.IsNullOrEmpty(JobStepIDForFailure) && CommandUtils.IsBuildMachine) { try { Contents = RunECTool(String.Format("getProperties --jobStepId {0} --recurse 1", JobStepIDForFailure), true); } catch (Exception Ex) { CommandUtils.Log(System.Diagnostics.TraceEventType.Warning, "Failed to get properties for jobstep to save them."); CommandUtils.Log(System.Diagnostics.TraceEventType.Warning, LogUtils.FormatException(Ex)); } } string RecordOfSuccess = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Saved", "Logs", NodeToDo.Name + Suffix + ".log"); CommandUtils.CreateDirectory(Path.GetDirectoryName(RecordOfSuccess)); CommandUtils.WriteAllText(RecordOfSuccess, Contents); TempStorage.StoreToTempStorage(CommandUtils.CmdEnv, NodeStoreName + Suffix, new List <string> { RecordOfSuccess }, !bSaveSharedTempStorage, GameNameIfAny); }
public void SaveStatus(TempStorageNodeInfo TempStorageNodeInfo, bool bSaveSharedTempStorage, string JobStepIDForFailure = null) { string Contents = "Just a status record: " + TempStorageNodeInfo.NodeStorageName; if (!String.IsNullOrEmpty(JobStepIDForFailure) && CommandUtils.IsBuildMachine) { try { Contents = RunECTool(String.Format("getProperties --jobStepId {0} --recurse 1", JobStepIDForFailure), true); } catch (Exception Ex) { CommandUtils.LogWarning("Failed to get properties for jobstep to save them."); CommandUtils.LogWarning(LogUtils.FormatException(Ex)); } } string RecordOfSuccess = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, "Engine", "Saved", "Logs", TempStorageNodeInfo.NodeStorageName + ".log"); CommandUtils.CreateDirectory(Path.GetDirectoryName(RecordOfSuccess)); CommandUtils.WriteAllText(RecordOfSuccess, Contents); TempStorage.StoreToTempStorage(TempStorageNodeInfo, new List <string> { RecordOfSuccess }, !bSaveSharedTempStorage, CommandUtils.CmdEnv.LocalRoot); }
/// <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); } } 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)); } }
/// <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, List <string> IniKeyBlacklist = null, List <string> IniSectionBlacklist = null) { 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 (IniKeyBlacklist != null && Path.GetExtension(SourceName) == ".ini") { FilterIniFile(SourceName, TargetName, IniKeyBlacklist, IniSectionBlacklist); // ini files may change size, don't check bSkipSizeCheck = true; } else { if (File.Exists(SourceName)) { File.Copy(SourceName, TargetName, overwrite: true); } else { Log.TraceInformation("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.TraceInformation("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.TraceInformation("Date mismatch {0} = {1} to {2} = {3}", SourceName, SourceInfo.LastWriteTimeUtc, TargetName, TargetInfo.LastWriteTimeUtc); Retry = true; } } } catch (Exception Ex) { Log.TraceInformation("SafeCopyFile Exception was {0}", LogUtils.FormatException(Ex)); Retry = true; } if (Retry) { if (Attempts + 1 < MaxAttempts) { Log.TraceInformation("Failed to copy {0} to {1}, deleting, waiting 10s and retrying.", SourceName, TargetName); if (File.Exists(TargetName)) { SafeDeleteFile(TargetName); } Thread.Sleep(10000); } else { Log.TraceError("Failed to copy {0} to {1}", SourceName, TargetName); } Result = false; } }while (Result == false && ++Attempts < MaxAttempts); return(Result); }
/// <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); }
public static int Main() { var CommandLine = SharedUtils.ParseCommandLine(); LogUtils.InitLogging(CommandLine); ErrorCodes ReturnCode = ErrorCodes.Error_Success; try { HostPlatform.Initialize(); Log.TraceVerbose("Running on {0} as a {1}-bit process.", HostPlatform.Current.GetType().Name, Environment.Is64BitProcess ? 64 : 32); 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); // Don't allow simultaneous execution of AT (in the same branch) InternalUtils.RunSingleInstance(MainProc, CommandLine); } catch (Exception Ex) { // Catch all exceptions and propagate the ErrorCode if we are given one. Log.WriteLine(TraceEventType.Error, "AutomationTool terminated with exception:"); Log.WriteLine(TraceEventType.Error, LogUtils.FormatException(Ex)); // set the exit code of the process if (Ex is AutomationException) { ReturnCode = (Ex as AutomationException).ErrorCode; } else { ReturnCode = ErrorCodes.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.WriteLine(TraceEventType.Information, "AutomationTool exiting with ExitCode={0}", 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); }
public static List <string> FindTempStorageManifests(CommandEnvironment Env, string StorageBlockName, bool LocalOnly = false, bool SharedOnly = false, string GameFolder = "") { var Files = new List <string>(); var LocalFiles = LocalTempStorageManifestFilename(Env, StorageBlockName); var LocalParent = Path.GetDirectoryName(LocalFiles); var WildCard = Path.GetFileName(LocalFiles); int IndexOfStar = WildCard.IndexOf("*"); if (IndexOfStar < 0 || WildCard.LastIndexOf("*") != IndexOfStar) { throw new AutomationException("Wildcard {0} either has no star or it has more than one.", WildCard); } string PreStarWildcard = WildCard.Substring(0, IndexOfStar); string PostStarWildcard = Path.GetFileNameWithoutExtension(WildCard.Substring(IndexOfStar + 1)); if (!SharedOnly && DirectoryExists_NoExceptions(LocalParent)) { foreach (var ThisFile in CommandUtils.FindFiles_NoExceptions(WildCard, true, LocalParent)) { Log(" Found local file {0}", ThisFile); int IndexOfWildcard = ThisFile.IndexOf(PreStarWildcard); if (IndexOfWildcard < 0) { throw new AutomationException("File {0} didn't contain {1}.", ThisFile, PreStarWildcard); } int LastIndexOfWildcardTail = ThisFile.LastIndexOf(PostStarWildcard); if (LastIndexOfWildcardTail < 0 || LastIndexOfWildcardTail < IndexOfWildcard + PreStarWildcard.Length) { throw new AutomationException("File {0} didn't contain {1} or it was before the prefix", ThisFile, PostStarWildcard); } string StarReplacement = ThisFile.Substring(IndexOfWildcard + PreStarWildcard.Length, LastIndexOfWildcardTail - IndexOfWildcard - PreStarWildcard.Length); if (StarReplacement.Length < 1) { throw new AutomationException("Dir {0} didn't have any string to fit the star in the wildcard {1}", ThisFile, WildCard); } if (!Files.Contains(StarReplacement)) { Files.Add(StarReplacement); } } } if (!LocalOnly) { var SharedFiles = SharedTempStorageManifestFilename(Env, StorageBlockName, GameFolder); var SharedParent = Path.GetDirectoryName(Path.GetDirectoryName(SharedFiles)); if (DirectoryExists_NoExceptions(SharedParent)) { string[] Dirs = null; try { Dirs = Directory.GetDirectories(SharedParent, Path.GetFileNameWithoutExtension(SharedFiles), SearchOption.TopDirectoryOnly); } catch (Exception Ex) { Log("Unable to Find Directories in {0} with wildcard {1}", SharedParent, Path.GetFileNameWithoutExtension(SharedFiles)); Log(" Exception was {0}", LogUtils.FormatException(Ex)); } if (Dirs != null) { foreach (var ThisSubDir in Dirs) { int IndexOfWildcard = ThisSubDir.IndexOf(PreStarWildcard); if (IndexOfWildcard < 0) { throw new AutomationException("Dir {0} didn't contain {1}.", ThisSubDir, PreStarWildcard); } int LastIndexOfWildcardTail = ThisSubDir.LastIndexOf(PostStarWildcard); if (LastIndexOfWildcardTail < 0 || LastIndexOfWildcardTail < IndexOfWildcard + PreStarWildcard.Length) { throw new AutomationException("Dir {0} didn't contain {1} or it was before the prefix", ThisSubDir, PostStarWildcard); } string StarReplacement = ThisSubDir.Substring(IndexOfWildcard + PreStarWildcard.Length, LastIndexOfWildcardTail - IndexOfWildcard - PreStarWildcard.Length); if (StarReplacement.Length < 1) { throw new AutomationException("Dir {0} didn't have any string to fit the star in the wildcard {1}", ThisSubDir, WildCard); } // these are a bunch of false positives if (StarReplacement.Contains("-")) { continue; } if (!Files.Contains(StarReplacement)) { Files.Add(StarReplacement); } } } } } var OutFiles = new List <string>(); foreach (var StarReplacement in Files) { var NewBlock = StorageBlockName.Replace("*", StarReplacement); if (TempStorageExists(Env, NewBlock, GameFolder, LocalOnly, true)) { OutFiles.Add(StarReplacement); } } return(OutFiles); }
/// <summary> /// Compiles all script modules. /// </summary> /// <param name="Modules">Module project filenames.</param> private static void CompileModules(List <string> Modules) { string DependencyFile = Path.Combine(CommandUtils.CmdEnv.EngineSavedFolder, "UATModuleHashes.xml"); if (AreDependenciesUpToDate(Modules, DependencyFile) && !GlobalCommandLine.IgnoreDependencies) { Log.TraceInformation("Dependencies are up to date. Skipping compile."); return; } Log.TraceInformation("Dependencies are out of date. Compiling scripts...."); // clean old assemblies CleanupScriptsAssemblies(); DateTime StartTime = DateTime.Now; string BuildTool = CommandUtils.CmdEnv.MsBuildExe; // msbuild (standard on windows, in mono >=5.0 is preferred due to speed and parallel compilation) bool UseParallelMsBuild = Path.GetFileNameWithoutExtension(BuildTool).ToLower() == "msbuild"; if (UseParallelMsBuild) { string ModulesList = string.Join(";", Modules); // Mono has an issue where arugments with semicolons or commas can't be passed through to // as arguments so we need to manually construct a temp file with the list of modules // see (https://github.com/Microsoft/msbuild/issues/471) var UATProjTemplate = CommandUtils.CombinePaths(CommandUtils.CmdEnv.LocalRoot, @"Engine\Source\Programs\AutomationTool\Scripts\UAT.proj"); var UATProjFile = Path.Combine(CommandUtils.CmdEnv.EngineSavedFolder, "UATTempProj.proj"); string ProjContents = File.ReadAllText(UATProjTemplate); ProjContents = ProjContents.Replace("$(Modules)", ModulesList); Directory.CreateDirectory(Path.GetDirectoryName(UATProjFile)); File.WriteAllText(UATProjFile, ProjContents); string MsBuildVerbosity = Log.OutputLevel >= LogEventType.Verbose ? "minimal" : "quiet"; var CmdLine = String.Format("\"{0}\" /p:Configuration={1} /verbosity:{2} /nologo", UATProjFile, BuildConfig, MsBuildVerbosity); // suppress the run command because it can be long and intimidating, making the logs around this code harder to read. var Result = CommandUtils.Run(BuildTool, CmdLine, Options: CommandUtils.ERunOptions.Default | CommandUtils.ERunOptions.NoLoggingOfRunCommand | CommandUtils.ERunOptions.LoggingOfRunDuration); if (Result.ExitCode != 0) { throw new AutomationException(String.Format("Failed to build \"{0}\":{1}{2}", UATProjFile, Environment.NewLine, Result.Output)); } } else { // Make sure DefaultScriptsDLLName is compiled first var DefaultScriptsProjName = Path.ChangeExtension(DefaultScriptsDLLName, "csproj"); // Primary modules must be built first List <string> PrimaryModules = Modules.Where(M => M.IndexOf(DefaultScriptsProjName, StringComparison.InvariantCultureIgnoreCase) >= 0).ToList(); foreach (var ModuleName in PrimaryModules) { Log.TraceInformation("Building script module: {0}", ModuleName); try { CompileScriptModule(ModuleName); } catch (Exception Ex) { CommandUtils.LogError(LogUtils.FormatException(Ex)); throw new AutomationException("Failed to compile module {0}", ModuleName); } break; } // Second pass, compile everything else List <string> SecondaryModules = Modules.Where(M => !PrimaryModules.Contains(M)).ToList(); // Non-parallel method foreach (var ModuleName in SecondaryModules) { Log.TraceInformation("Building script module: {0}", ModuleName); try { CompileScriptModule(ModuleName); } catch (Exception Ex) { CommandUtils.LogError(LogUtils.FormatException(Ex)); throw new AutomationException("Failed to compile module {0}", ModuleName); } } } TimeSpan Duration = DateTime.Now - StartTime; Log.TraceInformation("Compiled {0} modules in {1} secs", Modules.Count, Duration.TotalSeconds); HashCollection NewHashes = HashModules(Modules); if (NewHashes == null) { Log.TraceWarning("Failed to save dependency info!"); } else { NewHashes.SaveToFile(DependencyFile); Log.TraceVerbose("Wrote depencencies to {0}", DependencyFile); } }
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 && !Utils.IsRunningOnMono) { ProcessManager.KillAll(); } Log.WriteLine(TraceEventType.Information, "AutomationTool exiting with ExitCode={0}", ReturnCode); LogUtils.CloseFileLogging(); return(ReturnCode); }