/// <summary> /// Extracts the embedded compressed library to the location in the Filepath property /// </summary> public void Extract() { if (IsExtracted) { Logging.Warning("Unmanaged library {0} is already extracted", EmbeddedFilename); return; } if (File.Exists(Filepath)) { File.Delete(Filepath); } //https://stackoverflow.com/questions/38381684/reading-zip-file-from-byte-array-using-ionic-zip string resourceName = CommonUtils.GetAssemblyName(EmbeddedFilename); Logging.Info("Extracting unmanaged teximpnet library: {0}", EmbeddedFilename); using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) using (ZipFile zout = ZipFile.Read(stream)) { zout.ExtractAll(Settings.RelhaxLibrariesFolderPath); } }
/// <summary> /// Loads/serializes an xml file into a settings class based on class type /// </summary> /// <param name="xmlfile">The path to the file</param> /// <param name="SettingsClass">The type of the settings class to load into</param> /// <param name="propertiesToExclude">A string list of properties (in the class) to not look for. If none, you can pass in null</param> /// <param name="classInstance">The object to append the xml settings to. If the settings class is static, pass in null</param> /// <returns>Success if loading, false otherwise</returns> public static bool LoadSettings(string xmlfile, Type SettingsClass, string[] propertiesToExclude, object classInstance) { //first check if the file even exists if (!File.Exists(xmlfile)) { Logging.Info("Xml settings file {0} does not exist, using defaults set in class '{1}'", xmlfile, SettingsClass.Name.ToString()); return(false); } //get all fields from the class FieldInfo[] fields = SettingsClass.GetFields(); //get all types from the types in the class List <Type> typesOfTypesInClass = new List <Type>(); foreach (FieldInfo fieldInClass in fields) { //https://stackoverflow.com/questions/5090224/reflection-get-type-of-fieldinfo-object Type t = fieldInClass.FieldType; if (!typesOfTypesInClass.Contains(t)) { typesOfTypesInClass.Add(t); } } //now we have a list of all "types" that exist in the class //parse the xml list XmlDocument doc = new XmlDocument(); try { doc.Load(xmlfile); } catch (XmlException ex) { Logging.Error("Failed to load {0}, using defaults set in class{1}{2}{3}", xmlfile, SettingsClass.GetType().ToString(), Environment.NewLine, ex.ToString()); return(false); } //using child of child rather than xpath gets around the fact that the root element name has changed or can change XmlNodeList settings = doc.ChildNodes[0].ChildNodes; //legacy compatibility: if it's modpackSettings, there's some V1 bad names that need to be manually parsed if (SettingsClass.Equals(typeof(ModpackSettings))) { ModpackSettings.ApplyOldSettings(settings); } for (int i = 0; i < settings.Count; i++) { //verify that the setting name in xml matches a fieldInfo property in the class FieldInfo[] matches = fields.Where(f => f.Name.Equals(settings[i].Name)).ToArray(); //Logging.WriteToLog(string.Empty + matches.Count() + " matches for xml setting name " + settings[i].Name, Logfiles.Application, LogLevel.Debug); if (matches.Count() > 1) { throw new BadMemeException("ugh"); } else if (matches.Count() == 0) { Logging.Warning("no match for xml setting {0}", settings[i].Name); } else { FieldInfo settingField = matches[0]; //we have, based on name, matched the xml property to a property in the class //now set the value //BUT also check to make sure the item is not on the blacklist if (propertiesToExclude != null && propertiesToExclude.Contains(settingField.Name)) { Logging.Debug("Property {0} matched to exclusion list, skipping", settingField.Name); continue; } //get the type of the field and make sure it actually exists in the list (it should) if (typesOfTypesInClass.Contains(settingField.FieldType)) { //since the type exists, it *should* save //https://stackoverflow.com/questions/2380467/c-dynamic-parse-from-system-type try { var converter = TypeDescriptor.GetConverter(settingField.FieldType); if (classInstance != null) { settingField.SetValue(classInstance, converter.ConvertFrom(settings[i].InnerText)); } else { settingField.SetValue(SettingsClass, converter.ConvertFrom(settings[i].InnerText)); } } catch (Exception e) { Logging.Debug("failed to load property to memory {0}{1}{2}", settingField.Name, Environment.NewLine, e.ToString()); } } else { throw new BadMemeException("hmmmmmm"); } } } return(true); }
//when application is starting for first time private void Application_Startup(object sender, StartupEventArgs e) { //handle any assembly resolves //https://stackoverflow.com/a/19806004/3128017 AppDomain.CurrentDomain.AssemblyResolve += (sender2, bargs) => { string dllName = new AssemblyName(bargs.Name).Name + ".dll"; Assembly assem = Assembly.GetExecutingAssembly(); string resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn => rn.EndsWith(dllName)); using (Stream stream = assem.GetManifestResourceStream(resourceName)) { byte[] assemblyData = new byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); Logging.Debug("an assembly was loaded via AssemblyResolve: {0}", dllName); return(Assembly.Load(assemblyData)); } }; //init logging here //"The application failed to open a logfile. Either check your file permissions or move the application to a folder with write access" if (!Logging.Init(Logfiles.Application)) { MessageBox.Show(Translations.GetTranslatedString("appFailedCreateLogfile")); Shutdown((int)ReturnCodes.LogfileError); } Logging.WriteHeader(Logfiles.Application); Logging.Info(string.Format("| Relhax Modpack version {0}", Utils.GetApplicationVersion())); Logging.Info(string.Format("| Build version {0}, from date {1}", Settings.ApplicationVersion.ToString(), Utils.GetCompileTime())); Logging.Info(string.Format("| Running on OS {0}", Environment.OSVersion.ToString())); //parse command line arguments here //get the command line args for testing of auto install CommandLineSettings.ParseCommandLine(Environment.GetCommandLineArgs()); Logging.Debug("starting application in {0} mode", CommandLineSettings.ApplicationMode.ToString()); //switch into application modes based on mode enum switch (CommandLineSettings.ApplicationMode) { case ApplicationMode.Updater: DatabaseUpdater updater = new DatabaseUpdater(); CloseApplicationLog(true); //start updater logging system if (!Logging.Init(Logfiles.Updater)) { MessageBox.Show("Failed to initialize logfile for updater"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.Updater); updater.ShowDialog(); //stop updater logging system CloseLog(Logfiles.Updater); updater = null; Current.Shutdown(0); break; case ApplicationMode.Editor: DatabaseEditor editor = new DatabaseEditor(); CloseApplicationLog(true); //start updater logging system if (!Logging.Init(Logfiles.Editor)) { MessageBox.Show("Failed to initialize logfile for editor"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.Editor); editor.ShowDialog(); //stop updater logging system CloseLog(Logfiles.Editor); editor = null; Current.Shutdown(0); break; case ApplicationMode.PatchDesigner: PatchDesigner patcher = new PatchDesigner(); CloseApplicationLog(true); //start updater logging system if (!Logging.Init(Logfiles.PatchDesigner)) { MessageBox.Show("Failed to initialize logfile for patcher"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.PatchDesigner); patcher.ShowDialog(); //stop updater logging system CloseLog(Logfiles.PatchDesigner); patcher = null; Current.Shutdown(0); break; case ApplicationMode.Patcher: Logging.Info("Running patch mode"); if (CommandLineSettings.PatchFilenames.Count == 0) { Logging.Error("0 patch files parsed from command line!"); Current.Shutdown(-3); } else { List <Patch> patchList = new List <Patch>(); foreach (string file in CommandLineSettings.PatchFilenames) { if (!File.Exists(file)) { Logging.Warning("skipping file path {0}, not found", file); continue; } Logging.Info("adding patches from file {0}", file); XmlUtils.AddPatchesFromFile(patchList, file); } if (patchList.Count == 0) { Logging.Error("0 patches parsed from files!"); Current.Shutdown(-4); } PatchExitCode exitCode = PatchExitCode.Success; //always return on worst condition int i = 1; foreach (Patch p in patchList) { Logging.Info("running patch {0} of {1}", i++, patchList.Count); PatchExitCode exitCodeTemp = PatchUtils.RunPatch(p); if ((int)exitCodeTemp < (int)exitCode) { exitCode = exitCodeTemp; } } Logging.Info("patching finished, exit code {0} ({1})", (int)exitCode, exitCode.ToString()); CloseApplicationLog(true); Current.Shutdown((int)exitCode); } break; } }
//when application is starting for first time private void Application_Startup(object sender, StartupEventArgs e) { if (!Logging.Init(Logfiles.Application)) { //check if it's because the file already exists, or some other actual reason //if the file exists, and it's locked (init failed), then check if also the command line is creating a new window if (File.Exists(Logging.GetLogfile(Logfiles.Application).Filepath) && CommandLineSettings.ArgsOpenCustomWindow) { //a custom window will be open, so open the log in a custom name (with the application mode). it's ok in this case, because the likely cause //is that the modpack is open in a regular window and now we want to open a custom window Logging.DisposeLogging(Logfiles.Application); if (!Logging.Init(Logfiles.Application, Logging.ApplicationTempLogFilename)) { MessageBox.Show(string.Format("Failed to initialize logfile {0}, check file permissions", Logging.ApplicationTempLogFilename)); Shutdown((int)ReturnCodes.LogfileError); return; } } else { if (!Translations.TranslationsLoaded) { Translations.LoadTranslations(false); } //old message from Logging.Init //MessageBox.Show(string.Format("Failed to initialize logfile {0}, check file permissions", logfilePath)); MessageBox.Show(Translations.GetTranslatedString("appFailedCreateLogfile")); Shutdown((int)ReturnCodes.LogfileError); return; } } //handle any assembly resolves //https://stackoverflow.com/a/19806004/3128017 AppDomain.CurrentDomain.AssemblyResolve += (sender2, bargs) => { string dllName = new AssemblyName(bargs.Name).Name + ".dll"; Assembly assem = Assembly.GetExecutingAssembly(); string resourceName = assem.GetManifestResourceNames().FirstOrDefault(rn => rn.EndsWith(dllName)); using (Stream stream = assem.GetManifestResourceStream(resourceName)) { byte[] assemblyData = new byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); Logging.Debug("An assembly was loaded via AssemblyResolve: {0}", dllName); return(Assembly.Load(assemblyData)); } }; Logging.WriteHeader(Logfiles.Application); Logging.Info(string.Format("| Relhax Modpack version {0}", CommonUtils.GetApplicationVersion())); Logging.Info(string.Format("| Build version {0}, from date {1}", Settings.ApplicationVersion.ToString(), CommonUtils.GetCompileTime())); Logging.Info(string.Format("| Running on OS {0}", Environment.OSVersion.ToString())); //parse command line arguments given to the application CommandLineSettings.ParseCommandLine(Environment.GetCommandLineArgs()); if ((!CommandLineSettings.ArgsOpenCustomWindow) && (!ModpackSettings.ValidFrameworkVersion)) { //https://github.com/Willster419/RelhaxModpack/issues/90 //try getting .net framework information //https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed //https://docs.microsoft.com/en-us/dotnet/api/system.environment.version?view=netcore-3.1 //https://stackoverflow.com/questions/19096841/how-to-get-the-version-of-the-net-framework-being-targeted Logging.Debug(".NET Framework version information"); int frameworkVersion = -1; try { RegistryKey key = RegistryUtils.GetRegistryKeys(new RegistrySearch() { Root = Registry.LocalMachine, Searchpath = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full" }); Logging.Debug("Registry: {0}", key.Name); foreach (string subkey in key.GetValueNames()) { object value = key.GetValue(subkey); Logging.Debug("Registry: Subkey={0}, Value={1}", subkey, value.ToString()); if (subkey.ToLower().Equals("release")) { if (int.TryParse(value.ToString(), out int result)) { frameworkVersion = result; } else { Logging.Error("Unable to parse release value: {0}", value); } } } } catch (Exception ex) { Logging.Exception(ex.ToString()); } Logging.Info("Minimum required .NET Framework version: {0}, Installed: {1}", Settings.MinimumDotNetFrameworkVersionRequired, frameworkVersion); if (frameworkVersion == -1) { Logging.Error("Failed to get .NET Framework version from the registry"); MessageBox.Show("failedToGetDotNetFrameworkVersion"); } else if (frameworkVersion < Settings.MinimumDotNetFrameworkVersionRequired) { Logging.Error("Invalid .NET Framework version (less then 4.8)"); if (MessageBox.Show("invalidDotNetFrameworkVersion", "", MessageBoxButton.YesNo) == MessageBoxResult.Yes) { CommonUtils.StartProcess(Settings.DotNetFrameworkLatestDownloadURL); } } else { Logging.Info("Valid .NET Framework version"); ModpackSettings.ValidFrameworkVersion = true; } } //switch into application modes based on mode enum Logging.Debug("Starting application in {0} mode", CommandLineSettings.ApplicationMode.ToString()); switch (CommandLineSettings.ApplicationMode) { case ApplicationMode.Updater: ModpackToolbox updater = new ModpackToolbox(); //close application log if open if (Logging.IsLogOpen(Logfiles.Application)) { CloseApplicationLog(true); } //start updater logging if (!Logging.Init(Logfiles.Updater)) { MessageBox.Show("Failed to initialize logfile for updater"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.Updater); //redirect application log file to the modpack toolbox if (!Logging.RedirectLogOutput(Logfiles.Application, Logfiles.Updater)) { Logging.Error(Logfiles.Updater, LogOptions.MethodName, "Failed to redirect messages from application to modpack toolbox"); } //show window updater.ShowDialog(); //stop updater logging CloseLog(Logfiles.Updater); DeleteCustomLogIfExists(); updater = null; Current.Shutdown((int)ReturnCodes.Success); Environment.Exit((int)ReturnCodes.Success); return; case ApplicationMode.Editor: DatabaseEditor editor = new DatabaseEditor(); //close application log if open if (Logging.IsLogOpen(Logfiles.Application)) { CloseApplicationLog(true); } //start updater logging if (!Logging.Init(Logfiles.Editor)) { MessageBox.Show("Failed to initialize logfile for editor"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.Editor); //redirect application log file to the editor if (!Logging.RedirectLogOutput(Logfiles.Application, Logfiles.Editor)) { Logging.Error(Logfiles.Editor, LogOptions.MethodName, "Failed to redirect messages from application to editor"); } //show window editor.ShowDialog(); //stop updater logging CloseLog(Logfiles.Editor); DeleteCustomLogIfExists(); editor = null; Current.Shutdown((int)ReturnCodes.Success); Environment.Exit((int)ReturnCodes.Success); return; case ApplicationMode.PatchDesigner: PatchDesigner patcher = new PatchDesigner(); //close application log if open if (Logging.IsLogOpen(Logfiles.Application)) { CloseApplicationLog(true); } //start updater logging if (!Logging.Init(Logfiles.PatchDesigner)) { MessageBox.Show("Failed to initialize logfile for patcher"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.PatchDesigner); //redirect application log file to the patch designer if (!Logging.RedirectLogOutput(Logfiles.Application, Logfiles.PatchDesigner)) { Logging.Error(Logfiles.PatchDesigner, LogOptions.MethodName, "Failed to redirect messages from application to patch designer"); } //show window patcher.ShowDialog(); //stop patch designer logging CloseLog(Logfiles.PatchDesigner); DeleteCustomLogIfExists(); patcher = null; Current.Shutdown((int)ReturnCodes.Success); Environment.Exit((int)ReturnCodes.Success); return; case ApplicationMode.AutomationRunner: DatabaseAutomationRunner automationRunner = new DatabaseAutomationRunner(); //close application log if open if (Logging.IsLogOpen(Logfiles.Application)) { CloseApplicationLog(true); } //start DatabaseAutomationRunner logging if (!Logging.Init(Logfiles.AutomationRunner)) { MessageBox.Show("Failed to initialize logfile for DatabaseAutomationRunner"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.AutomationRunner); //redirect application log file to the automation runner if (!Logging.RedirectLogOutput(Logfiles.Application, Logfiles.AutomationRunner)) { Logging.Error(Logfiles.AutomationRunner, LogOptions.MethodName, "Failed to redirect messages from application to automation runner"); } //show window automationRunner.ShowDialog(); //stop patch designer logging CloseLog(Logfiles.AutomationRunner); DeleteCustomLogIfExists(); automationRunner = null; Current.Shutdown((int)ReturnCodes.Success); Environment.Exit((int)ReturnCodes.Success); return; case ApplicationMode.Patcher: Logging.Info("Running patch mode"); //check that at least one patch file was specified from command line if (CommandLineSettings.PatchFilenames.Count == 0) { Logging.Error("0 patch files parsed from command line!"); Current.Shutdown((int)ReturnCodes.PatcherNoSpecifiedFiles); Environment.Exit((int)ReturnCodes.PatcherNoSpecifiedFiles); } else { //parse patch objects from command line file list List <Patch> patchList = new List <Patch>(); foreach (string file in CommandLineSettings.PatchFilenames) { if (!File.Exists(file)) { Logging.Warning("Skipping file path {0}, not found", file); continue; } Logging.Info("Adding patches from file {0}", file); XmlUtils.AddPatchesFromFile(patchList, file); } //check for at least one patchfile was parsed if (patchList.Count == 0) { Logging.Error("0 patches parsed from files!"); Current.Shutdown((int)ReturnCodes.PatcherNoPatchesParsed); Environment.Exit((int)ReturnCodes.PatcherNoPatchesParsed); } //set default patch return code PatchExitCode exitCode = PatchExitCode.Success; //always return on worst condition int i = 1; foreach (Patch p in patchList) { Logging.Info("Running patch {0} of {1}", i++, patchList.Count); PatchExitCode exitCodeTemp = PatchUtils.RunPatch(p); if ((int)exitCodeTemp < (int)exitCode) { exitCode = exitCodeTemp; } } Logging.Info("Patching finished, exit code {0} ({1})", (int)exitCode, exitCode.ToString()); CloseApplicationLog(true); //add 100 to ensure it's a patch unique error code Current.Shutdown(((int)exitCode) + 100); Environment.Exit(((int)exitCode) + 100); } return; } }
private void SelectWindowStartup() { //switch into application modes based on mode enum Logging.Debug("Starting application in {0} mode", CommandLineSettings.ApplicationMode.ToString()); switch (CommandLineSettings.ApplicationMode) { case ApplicationMode.Updater: ModpackToolbox updater = new ModpackToolbox(modpackSettings, Logfiles.Updater) { CommandLineSettings = CommandLineSettings, LaunchedFromMainWindow = false, RunStandAloneUpdateCheck = true }; //close application log if open if (Logging.IsLogOpen(Logfiles.Application)) { CloseApplicationLog(true); } //start updater logging if (!Logging.Init(Logfiles.Updater, modpackSettings.VerboseLogging, true)) { MessageBox.Show("Failed to initialize logfile for updater"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.Updater); //redirect application log file to the modpack toolbox if (!Logging.RedirectLogOutput(Logfiles.Application, Logfiles.Updater)) { Logging.Error(Logfiles.Updater, LogOptions.MethodName, "Failed to redirect messages from application to modpack toolbox"); } //show window updater.Show(); break; case ApplicationMode.Editor: DatabaseEditor editor = new DatabaseEditor(modpackSettings, Logfiles.Editor) { CommandLineSettings = CommandLineSettings, LaunchedFromMainWindow = false, RunStandAloneUpdateCheck = true }; //close application log if open if (Logging.IsLogOpen(Logfiles.Application)) { CloseApplicationLog(true); } //start updater logging if (!Logging.Init(Logfiles.Editor, modpackSettings.VerboseLogging, true)) { MessageBox.Show("Failed to initialize logfile for editor"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.Editor); //redirect application log file to the editor if (!Logging.RedirectLogOutput(Logfiles.Application, Logfiles.Editor)) { Logging.Error(Logfiles.Editor, LogOptions.MethodName, "Failed to redirect messages from application to editor"); } //show window editor.Show(); break; case ApplicationMode.PatchDesigner: PatchDesigner patcher = new PatchDesigner(modpackSettings, Logfiles.PatchDesigner) { CommandLineSettings = CommandLineSettings, LaunchedFromMainWindow = false, RunStandAloneUpdateCheck = true }; //close application log if open if (Logging.IsLogOpen(Logfiles.Application)) { CloseApplicationLog(true); } //start updater logging if (!Logging.Init(Logfiles.PatchDesigner, modpackSettings.VerboseLogging, true)) { MessageBox.Show("Failed to initialize logfile for patcher"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.PatchDesigner); //redirect application log file to the patch designer if (!Logging.RedirectLogOutput(Logfiles.Application, Logfiles.PatchDesigner)) { Logging.Error(Logfiles.PatchDesigner, LogOptions.MethodName, "Failed to redirect messages from application to patch designer"); } //show window patcher.Show(); break; case ApplicationMode.AutomationRunner: DatabaseAutomationRunner automationRunner = new DatabaseAutomationRunner(modpackSettings, Logfiles.AutomationRunner) { CommandLineSettings = CommandLineSettings, LaunchedFromMainWindow = false, RunStandAloneUpdateCheck = true }; //close application log if open if (Logging.IsLogOpen(Logfiles.Application)) { CloseApplicationLog(true); } //start DatabaseAutomationRunner logging if (!Logging.Init(Logfiles.AutomationRunner, modpackSettings.VerboseLogging, true)) { MessageBox.Show("Failed to initialize logfile for DatabaseAutomationRunner"); Current.Shutdown((int)ReturnCodes.LogfileError); return; } Logging.WriteHeader(Logfiles.AutomationRunner); //redirect application log file to the automation runner if (!Logging.RedirectLogOutput(Logfiles.Application, Logfiles.AutomationRunner)) { Logging.Error(Logfiles.AutomationRunner, LogOptions.MethodName, "Failed to redirect messages from application to automation runner"); } //show window automationRunner.Show(); break; case ApplicationMode.Patcher: //check that at least one patch file was specified from command line if (CommandLineSettings.PatchFilenames.Count == 0) { Logging.Error("0 patch files parsed from command line!"); Current.Shutdown((int)ReturnCodes.PatcherNoSpecifiedFiles); Environment.Exit((int)ReturnCodes.PatcherNoSpecifiedFiles); } else { //parse patch objects from command line file list List <Instruction> patchList = new List <Instruction>(); InstructionLoader loader = new InstructionLoader(); foreach (string file in CommandLineSettings.PatchFilenames) { if (!File.Exists(file)) { Logging.Warning("Skipping file path {0}, not found", file); continue; } Logging.Info("Adding patches from file {0}", file); loader.AddInstructionObjectsToList(file, patchList, InstructionsType.Patch, Patch.PatchXmlSearchPath); } //check for at least one patchfile was parsed if (patchList.Count == 0) { Logging.Error("0 patches parsed from files!"); Current.Shutdown((int)ReturnCodes.PatcherNoPatchesParsed); Environment.Exit((int)ReturnCodes.PatcherNoPatchesParsed); } //set default patch return code PatcherExitCode = PatchExitCode.Success; //always return on worst condition int i = 1; //TODO: does WoTDirectory get set later? maybe tm? Patcher thePatcher = new Patcher() { WoTDirectory = null }; foreach (Patch p in patchList) { Logging.Info("Running patch {0} of {1}", i++, patchList.Count); PatchExitCode exitCodeTemp = thePatcher.RunPatchFromCommandline(p); if ((int)exitCodeTemp < (int)PatcherExitCode) { PatcherExitCode = exitCodeTemp; } } } break; case ApplicationMode.Default: MainWindow window = new MainWindow(modpackSettings) { CommandLineSettings = CommandLineSettings }; window.Show(); break; } }
/// <summary> /// Run a complete regression test based on the list of unit tests /// </summary> /// <returns>Returns false if a setup error occurred, true otherwise</returns> /// <remarks>The return value of the method does NOT related to the success of the Unit Tests</remarks> public bool RunRegressions() { //if from the editor, enable verbose logging (allows it to get debug log statements) bool tempVerboseLoggingSetting = ModpackSettings.VerboseLogging; if (!ModpackSettings.VerboseLogging) { Logging.Info("p.FromEditor=true and ModpackSettings.VerboseLogging=false, setting to true for duration of patch method"); ModpackSettings.VerboseLogging = true; } //init the logfile for regressions if (File.Exists(RegressionLogfile.Filepath)) { Logging.Warning("regression log file previously exists, deleting..."); File.Delete(RegressionLogfile.Filepath); } if (!RegressionLogfile.Init()) { Logging.Error("failed to initialize logfile"); return(false); } //make sure the files to test against exist first //and the start file if (!File.Exists(Path.Combine(RegressionFolderPath, Startfile))) { Logging.Error("regressions start file does not exist!"); Logging.Error(Path.Combine(RegressionFolderPath, Startfile)); return(false); } for (int i = 1; i < UnitTests.Count + 1; i++) { string checkfile = Path.Combine(RegressionFolderPath, string.Format("{0}{1}{2}", CheckFilenamePrefix, i.ToString("D2"), RegressionExtension)); if (!File.Exists(checkfile)) { Logging.Error("checkfile does not exist!"); Logging.Error(checkfile); return(false); } } //make a new file to be the one to make changes to //path get extension gets the dot string filenameToTest = "testfile" + RegressionExtension; string filenameToTestPath = Path.Combine(RegressionFolderPath, filenameToTest); if (File.Exists(filenameToTestPath)) { File.Delete(filenameToTestPath); } File.Copy(Path.Combine(RegressionFolderPath, Startfile), filenameToTestPath); WriteToLogfiles("----- Unit tests start -----"); bool breakOutEarly = false; foreach (UnitTest unitTest in UnitTests) { unitTest.Patch.CompletePath = filenameToTestPath; unitTest.Patch.File = filenameToTestPath; unitTest.Patch.Type = RegressionTypeString; WriteToLogfiles("Running test {0} of {1}: {2}", ++NumPassed, UnitTests.Count, unitTest.Description); unitTest.Patch.FromEditor = true; if (unitTest.Patch.FollowPath) { //delete testfile if (File.Exists(filenameToTestPath)) { File.Delete(filenameToTestPath); } if (NumPassed >= 5) { File.Copy(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"check_04", RegressionExtension)), filenameToTestPath); if (NumPassed == 6) { //backup currentPlayersPanel and copy over new one if (File.Exists(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanelBackup", RegressionExtension)))) { File.Delete(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanelBackup", RegressionExtension))); } File.Copy(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension)), Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanelBackup", RegressionExtension))); if (File.Exists(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension)))) { File.Delete(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension))); } File.Copy(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"check_05", RegressionExtension)), Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension))); } else if (NumPassed == 7) { if (File.Exists(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension)))) { File.Delete(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension))); } File.Copy(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"check_06", RegressionExtension)), Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension))); } } else { File.Copy(Path.Combine(RegressionFolderPath, Startfile), filenameToTestPath); } } PatchUtils.RunPatch(unitTest.Patch); string checkfile = Path.Combine(RegressionFolderPath, string.Format("{0}{1}{2}", CheckFilenamePrefix, NumPassed.ToString("D2"), Path.GetExtension(Startfile))); WriteToLogfiles("Checking results against check file {0}...", Path.GetFileName(checkfile)); string patchRun = File.ReadAllText(filenameToTestPath); string patchTestAgainst = File.ReadAllText(checkfile); if (patchTestAgainst.Equals(patchRun)) { WriteToLogfiles("Success!"); } else { WriteToLogfiles("Failed!"); breakOutEarly = true; break; } } if (breakOutEarly) { WriteToLogfiles("----- Unit tests finish (fail)-----"); } else { WriteToLogfiles("----- Unit tests finish (pass)-----"); //delete the test file, we don't need it. (it's the same text as the last check file anyways) if (File.Exists(filenameToTestPath)) { File.Delete(filenameToTestPath); } if (UnitTests[0].Patch.FollowPath) { //delete not needed "escaped" files and put playersPanelBackup back if (File.Exists(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension)))) { File.Delete(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension))); } File.Copy(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanelBackup", RegressionExtension)), Path.Combine(RegressionFolderPath, string.Format("{0}{1}", @"playersPanel", RegressionExtension))); foreach (string file in new string[] { "battleLabelsTemplates_escaped", "battleLabels_escaped", "damageLog_escaped", "playersPanel_escaped", "testfile_escaped", "playersPanelBackup" }) { if (File.Exists(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", file, RegressionExtension)))) { File.Delete(Path.Combine(RegressionFolderPath, string.Format("{0}{1}", file, RegressionExtension))); } } } } //dispose log file RegressionLogfile.Dispose(); //set the verbose setting back Logging.Debug("temp logging setting={0}, ModpackSettings.VerboseLogging={1}, setting logging back to temp"); ModpackSettings.VerboseLogging = tempVerboseLoggingSetting; return(true); }