/// <summary> /// attempt to write the monitor setup file to all configured Saved Games folders /// and also persist our viewports information /// </summary> /// <param name="callbacks"></param> /// <returns></returns> public override InstallationResult Install(IInstallationCallbacks callbacks) { try { if (!_parent.CheckMonitorsValid) { throw new Exception( "UI should have disabled monitor setup writing without up to date monitors; implementation error"); } if (string.IsNullOrWhiteSpace(_parent.Profile.Path)) { throw new Exception( "UI should have disabled monitor setup without a profile name; implementation error"); } // create template for combined monitor setup MonitorSetupTemplate combinedTemplate = CreateCombinedTemplate(); // gather all the results into a list to enumerate the yield returns List <StatusReportItem> results = new List <StatusReportItem>(EnumerateMonitorSetupFiles(InstallFile, combinedTemplate)); if (!_parent.GenerateCombined) { // add the same tests for separate monitor setup results.AddRange(EnumerateMonitorSetupFiles(InstallFile, CreateSeparateTemplate())); } // now scan results foreach (StatusReportItem item in results) { if (item.Severity >= StatusReportItem.SeverityCode.Error) { callbacks.Failure( "Monitor setup file generation has failed", "Some files may have been generated before the failure and these files were not removed.", results); return(InstallationResult.Fatal); } // REVISIT we should have simulated first to gather warnings and errors so we can show a danger prompt } _parent.Combined.Save(combinedTemplate.ProfileName, _localViewports); callbacks.Success( "Monitor setup generation successful", "Monitor setup files have been installed into DCS.", results); _parent.InvalidateStatusReport(); return(InstallationResult.Success); } catch (Exception ex) { ConfigManager.LogManager.LogError("failed to install monitor setup", ex); callbacks.Failure("Failed to install monitor setup", ex.Message, new List <StatusReportItem>()); _parent.InvalidateStatusReport(); return(InstallationResult.Fatal); } }
public abstract InstallationResult Install(IInstallationCallbacks callbacks);
public InstallationResult Uninstall(IInstallationCallbacks callbacks) { List <StatusReportItem> results = new List <StatusReportItem>(); bool failed = false; string message = ""; // load patchExclusions from settings instead of caching them, so we don't have different code paths from elevated binary HashSet <string> patchExclusions = LoadPatchExclusions(); // revert patches, by either restoring original file or reverse patching foreach (PatchApplication item in _destinations.Values) { if (!item.Enabled) { continue; } // revert directly or via elevated process, as appropriate item.PatchExclusions = patchExclusions; IList <StatusReportItem> revertResults = item.UseRemote ? item.RemoteRevert() : item.Revert(); foreach (StatusReportItem result in revertResults) { result.Log(ConfigManager.LogManager); results.Add(result); if (result.Severity < StatusReportItem.SeverityCode.Error) { continue; } if (!failed) { // keep first message message = $"Reverting patches in {item.Destination.LongDescription} failed\n{result.Status}\n{result.Recommendation}"; } failed = true; } // ReSharper disable once InvertIf early exit on error condition should have a block if (failed) { // give up and just direct the user to fix one installation this time, meaning they may have to do this multiple times message += $"\nPlease execute 'bin\\dcs_updater.exe repair' in your {item.Destination.LongDescription} to restore to original files"; break; } } UpdateStatus(); if (failed) { callbacks.Failure($"{_patchSetDescription} revert failed", message, results); return(InstallationResult.Fatal); } // special check that is not handled by UpdateStatus, because we are technically in a state that just means // we have to reinstall some patches, but this still means something went wrong in reverting patches, such as // user cancellation if (_destinations.Values.Any(d => d.Enabled && d.Status != StatusCodes.OutOfDate && d.Status != StatusCodes.NotApplicable)) { // revert completed, but not everything was done callbacks.Failure($"{_patchSetDescription} removal incomplete", "Some patches were not reverted", results); return(InstallationResult.Canceled); } callbacks.Success($"{_patchSetDescription} removal success", "All patches reverted successfully", results); return(InstallationResult.Success); }
public InstallationResult Install(IInstallationCallbacks callbacks) { List <StatusReportItem> results = new List <StatusReportItem>(); bool failed = false; bool imprecise = false; // load patchExclusions from settings instead of caching them, so we don't have different code paths from elevated binary HashSet <string> patchExclusions = LoadPatchExclusions(); // simulate patches and collect any errors foreach (PatchApplication item in _destinations.Values) { if (!item.Enabled) { continue; } item.PatchExclusions = patchExclusions; foreach (StatusReportItem result in item.Patches.SimulateApply(item.Destination, patchExclusions)) { result.Log(ConfigManager.LogManager); results.Add(result); if (result.Severity >= StatusReportItem.SeverityCode.Error) { failed = true; item.Status = StatusCodes.Incompatible; } if (result.Severity >= StatusReportItem.SeverityCode.Warning) { imprecise = true; } } } if (failed) { UpdateStatus(); callbacks.Failure($"{_patchSetDescription} installation would fail", "Some patches would fail to apply. No patches have been applied.", results); return(InstallationResult.Fatal); } if (imprecise) { InstallationPromptResult response = callbacks.DangerPrompt( $"{_patchSetDescription} installation may have risks", $"{_patchSetDescription} installation can continue, but some target files have changed since these patches were created.", results); if (response == InstallationPromptResult.Cancel) { return(InstallationResult.Canceled); } } // apply patches foreach (PatchApplication item in _destinations.Values) { if (!item.Enabled) { // destination is not selected for writing continue; } // apply patches directly or via elevated process, as appropriate IList <StatusReportItem> applyResults = item.UseRemote ? item.RemoteApply() : item.Apply(); foreach (StatusReportItem result in applyResults) { result.Log(ConfigManager.LogManager); results.Add(result); if (result.Severity >= StatusReportItem.SeverityCode.Error) { failed = true; } } } UpdateStatus(); if (failed) { // XXX need to revert any patches that were installed, if we can, and add to result report callbacks.Failure($"{_patchSetDescription} installation failed", "Some patches failed to be written", results); return(InstallationResult.Fatal); } if (Status != StatusCodes.UpToDate) { // installation completed, but not everything was done callbacks.Failure($"{_patchSetDescription} installation incomplete", "Not all patches were installed", results); return(InstallationResult.Canceled); } callbacks.Success($"{_patchSetDescription} installation success", "All patches installed successfully", results); return(InstallationResult.Success); }
public override InstallationResult Install(IInstallationCallbacks callbacks) => // use the generic patch installation to implement this Patching.Install(callbacks);