Files
UnrealEngineUWP/Engine/Source/Programs/AutomationTool/Program.cs
Wes Hunt cefa87e4b7 Ionic.zip code import
* Moving Ionic.Zip source code into UE4 from UE4 source.
* Only one left should be in Binaries/DotNET.
* Moving TPS info to source location.
* Deleting several copies that were floating around.

Assembly Resolve Refactor
* Added AssemblyUtils.InstallAssemblyResolver to handle resolving of known assemblies that may not exist in the same folder as the referencing assembly.
* This is now installed by UAT and UBT, which should handle all needs to load Ionic.Zip and RPCUtility.exe from scripts that install into subfolders of Binaries/DotNET.
* Other assemblies can be added easily as necesary, centralizing the location where this is handled.
* Removed AssemblyResolver from RPCUtilHelper as UBT handles it automatically now.
* Removed Ionic.Zip references from projects that weren't really using it.
#codereview:ben.marsh

[CL 2646891 by Wes Hunt in Main branch]
2015-08-06 15:55:44 -04:00

141 lines
5.3 KiB
C#

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
// This software is provided "as-is," without any express or implied warranty.
// In no event shall the author, nor Epic Games, Inc. be held liable for any damages arising from the use of this software.
// This software will not be supported.
// Use at your own risk.
using System;
using System.Threading;
using System.Diagnostics;
using UnrealBuildTool;
using System.Reflection;
using Tools.DotNETCommon;
using System.IO;
namespace AutomationTool
{
public class Program
{
[STAThread]
public static int Main()
{
var CommandLine = SharedUtils.ParseCommandLine();
LogUtils.InitLogging(CommandLine);
ErrorCodes ReturnCode = ErrorCodes.Error_Success;
try
{
// ensure we can resolve any external assemblies as necessary.
AssemblyUtils.InstallAssemblyResolver(Path.GetDirectoryName(Assembly.GetEntryAssembly().GetOriginalLocation()));
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 = 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(CtrlHandler);
var Version = AssemblyUtils.ExecutableVersion;
Log.TraceVerbose("{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.TraceError("AutomationTool terminated with exception: {0}", 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.TraceInformation("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;
}
/// <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));
}
}
static bool CtrlHandler(CtrlTypes EventType)
{
Domain_ProcessExit(null, null);
if (EventType == CtrlTypes.CTRL_C_EVENT)
{
// Force exit
Environment.Exit(3);
}
return true;
}
static void Domain_ProcessExit(object sender, EventArgs e)
{
// Kill all spawned processes (Console instead of Log because logging is closed at this time anyway)
Console.WriteLine("Domain_ProcessExit");
if (ShouldKillProcesses && !Utils.IsRunningOnMono)
{
ProcessManager.KillAll();
}
Trace.Close();
}
static void MainProc(object Param)
{
Automation.Process((string[])Param);
ShouldKillProcesses = Automation.ShouldKillProcesses;
}
static bool ShouldKillProcesses = true;
}
}