// Invoked when application is being started up (before MainWindow creation). private void App_Startup(object sender, StartupEventArgs e) { // Set main thread apartment state. Thread.CurrentThread.SetApartmentState(ApartmentState.STA); // Set AppUserModelId of current process. TaskbarHelper.SetAppUserModelId(); // Create Mutex if this is first instance. try { RunningInstanceMutex = Mutex.OpenExisting(RunningInstanceMutexName); } catch (WaitHandleCannotBeOpenedException) { bool created = false; RunningInstanceMutex = new Mutex(false, RunningInstanceMutexName, out created); if (!created) { throw new Exception("Unable to create application mutex"); } } // Load persistent data. // Take the first not-switch argument as path to the build that will be imported var importedBuildPath = e.Args.FirstOrDefault(s => !s.StartsWith("/")); PersistentData = PersistentDataSerializationService.CreatePersistentData(importedBuildPath); // Initialize localization. L10n.Initialize(PersistentData.Options.Language); }
public async Task FirstStepRemovesPinnedTaskbarIcon() { string roamingFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); string taskbarFolder = Path.Combine(roamingFolder, @"Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"); using (IntegrationTestHelper.WithClickOnceApp()) { var clickOnceInfo = UninstallInfo.Find(IntegrationTestHelper.ClickOnceAppName); string shortcutPath = clickOnceInfo.GetShortcutPath(); TaskbarHelper.PinToTaskbar(shortcutPath); string rootDir; using (IntegrationTestHelper.WithTempDirectory(out rootDir)) { using (var updateManager = IntegrationTestHelper.GetSquirrelUpdateManager(rootDir)) { using (IntegrationTestHelper.CleanupSquirrel(updateManager)) { var migrator = new InClickOnceAppMigrator(updateManager, IntegrationTestHelper.ClickOnceAppName); await migrator.Execute(); Assert.False(File.Exists(Path.Combine(taskbarFolder, IntegrationTestHelper.ClickOnceAppName + ".appref-ms"))); } } } } }
public static void SetProgressState(TaskbarButtonProgressMode State) { if (!cantInteractWithTaskbar && MainWindowHandle != IntPtr.Zero) { try { TaskbarHelper.SetProgressState(MainWindowHandle, State); } catch (Exception) { cantInteractWithTaskbar = true; } } }
// JumpListItemTask CreateJumpListTask(string caption, string iconName) { JumpListItemTask task = new JumpListItemTask(caption); task.IconPath = TaskbarHelper.GetIconPath(iconName); task.IconIndex = 0; return(task); }
public MainForm() { TaskbarHelper.InitDemoJumpList(TaskbarAssistant.Default, this); Program.MainForm = this; Icon = Program.AppIcon; ShowSplashScreen(); InitializeComponent(); PrepareUI(); InitViewModel(); DevExpress.Utils.About.UAlgo.Default.DoEventObject(DevExpress.Utils.About.UAlgo.kDemo, DevExpress.Utils.About.UAlgo.pWinForms, this); }
public static void SetProgressValue(ulong CurrentValue, ulong MaximumValue) { if (!cantInteractWithTaskbar && MainWindowHandle != IntPtr.Zero) { if (CurrentValue > MaximumValue) { throw new Exception($"WindowsTaskbarHelper.SetProgressValue: Incorrect parameters - Cur: {CurrentValue}, Max: {MaximumValue}."); } try { TaskbarHelper.SetProgressValue(MainWindowHandle, CurrentValue, MaximumValue); } catch (Exception) { cantInteractWithTaskbar = true; } } }
internal void OnStarted() { started = true; MiniProgressBar.IsIndeterminate = false; if (client.TransferEvent.IsUpload) { Title = AppLanguage.Get("LangTitleUploading_x").FormatC(0); } else { Title = AppLanguage.Get("LangTitleDownloading_x").FormatC(0); } GroupBoxCurrentX.Visibility = GroupBoxTotal.Visibility = Visibility.Visible; LabelETA.Visibility = Visibility.Visible; TransferProgress.Roll(false); TextBlockCounts.Visibility = Visibility.Collapsed; ButtonPause.Visibility = Visibility.Visible; if (client.TransferEvent.TotalFiles > 0) { LabelFilesXY.Content = AppLanguage.Get("LangLabelFiles_X_Y").FormatC(0, client.TransferEvent.TotalFiles); LabelFilesXY.Visibility = Visibility.Visible; } if (client.TransferEvent.TotalFolders > 0) { LabelFoldersXY.Content = AppLanguage.Get("LangLabelFolders_X_Y").FormatC(0, client.TransferEvent.TotalFolders); LabelFoldersXY.Visibility = Visibility.Visible; } cacher.TotalSize = SizeUnit.Parse(client.TransferEvent.TotalSize); LabelTotalSizeXY.Content = AppLanguage.Get("LangLabelTransferredSize_X_FromTotal_Y").FormatC(0, cacher.TotalSize); LabelTotalRemainsX.Content = AppLanguage.Get("LangLabelRemains_X").FormatC(cacher.TotalSize); maximum = client.TransferEvent.TotalFolders + client.TransferEvent.TotalFiles + client.TransferEvent.TotalSize; if (maximum == 0) { maximum = 1; } LabelTransferSpeed.Content = AppLanguage.Get("LangLabelAverageTransferSpeed_X").FormatC(SizeUnit.Parse(0)); ElapsedTimeLabel.Content = AppLanguage.Get("LangLabelElapsedTime_X").FormatC(zeroTime); LabelETA.Content = AppLanguage.Get("LangLabelETATime_X").FormatC(zeroTime); ButtonFished.Visibility = Visibility.Visible; TaskbarHelper.Add(ProgressBarTotal); timer200.Start(); timer1000.Start(); }
public frmMain() { TaskbarHelper.InitDemoJumpList(TaskbarAssistant.Default, this); InitializeComponent(); RibbonButtonsInitialize(); modulesNavigator = new ModulesNavigator(ribbonControl1, pcMain); zoomManager = new ZoomManager(ribbonControl1, modulesNavigator, beiZoom); InitNavBarItemLinks(); NavigationInitialize(); SetPageLayoutStyle(); guideGenerator = new GuideGenerator(); guideGenerator.CreateWhatsThisItem(ribbonControl1, () => { return(this); }); }
public frmMain() { TaskbarHelper.InitDemoJumpList(TaskbarAssistant.Default, this); InitializeComponent(); rpcSearch.Text = TagResources.SearchTools; InitNavBarGroups(); SkinHelper.InitSkinGallery(rgbiSkins); RibbonButtonsInitialize(); modulesNavigator = new ModulesNavigator(ribbonControl1, pcMain); zoomManager = new ZoomManager(ribbonControl1, modulesNavigator, beiZoom); modulesNavigator.ChangeGroup(navBarControl1.ActiveGroup, this); NavigationInitialize(); SetPageLayoutStyle(); }
public NotificationFlyoutApplication() { Uwp.UI.Controls.NotificationFlyout.SetApplication(this); _notificationIconHelper = NotificationIconHelper.Create(); _notificationIconHelper.IconInvoked += OnIconInvoked; _taskbarHelper = TaskbarHelper.Create(); _taskbarHelper.TaskbarChanged += OnTaskbarChanged; _systemPersonalisationHelper = SystemPersonalisationHelper.Current; _systemPersonalisationHelper.ThemeChanged += OnThemeChanged; PrepareFlyoutHost(); WndProcListener.Current.Start(); }
private void Timer_OnNewState(object sender, TimerState e) { Threading.ComponentInvoke(buttonManualBackup, (x) => x.Enabled = e == TimerState.SavingEnabled || e == TimerState.WaitingForCanvas); if (e == TimerState.NeverSaved) { TaskbarHelper.SetState(SaiHelper.AppProcess, TaskbarProgressBarState.Paused); } else if (e == TimerState.SavingEnabled) { TaskbarHelper.SetState(SaiHelper.AppProcess, TaskbarProgressBarState.Normal); } switch (e) { case TimerState.NeverSaved: Threading.SetComponentText(this, labelStatus, Properties.Strings.StateNeverSaved); break; case TimerState.SavingDisabled: Threading.SetComponentText(this, labelStatus, Properties.Strings.StateSavingDisabled); break; case TimerState.SavingEnabled: Threading.SetComponentText(this, labelStatus, Properties.Strings.StateSavingEnabled); break; case TimerState.WaitingForCanvas: Threading.SetComponentText(this, labelStatus, Properties.Strings.StateWaitingForCanvas); break; case TimerState.WaitingForProcess: Threading.SetComponentText(this, labelStatus, Properties.Strings.StateWaitingForProcess); break; case TimerState.WaitingForProject: Threading.SetComponentText(this, labelStatus, Properties.Strings.StateWaitingForProject); break; } BeginInvoke(new Action(() => sToolStripMenuItem.Text = labelStatus.Text)); }
/// <summary> /// Regenerates the window icon and set the taskbar status /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void UpdateTaskbarAndIcon(object sender, EventArgs e) { //Sets the taskbar progress of this window TaskbarUtility.SetProgress(this); //Sets the title of the window TaskbarUtility.SetTitle(this); //A new window icon must be created. This happens once per minute if (_lastMinuteIconWasCreated != Config.RealTimeLeft.Minutes) { _lastMinuteIconWasCreated = Config.RealTimeLeft.Minutes; //Create new pie Bitmap pie = TaskbarHelper.CreatePie( bounds: new Rectangle(0, 0, 64, 64), primary: Properties.Resources.clrUpper.GetPixel(Config.TimeLeft.Minutes, 0), secondary: Properties.Resources.clrLower.GetPixel(Config.TimeLeft.Minutes, 0), primaryBG: Properties.Resources.clrToGreen.GetPixel(Config.TimeLeft.Minutes, 0), secondaryBG: Properties.Resources.clrToRed.GetPixel(Config.TimeLeft.Minutes, 0), value: (float)Config.TimeLeft.TotalMinutes / 60f, startAngle: (int)Math.Floor(Config.Target.Minute / 60f * 360 - 90), ccw: !Config.Overtime ); //Update icon Icon = TaskbarHelper.CreateIconFromBitmap(pie); pie.Dispose(); } //We have reached overtime. Make background red. This happens only once if (Config.Overtime && !_overtimeBackColorSet) { foreach (Control i in tabs.Controls) { i.BackColor = Config.GlobalOvertimeColor; } _overtimeBackColorSet = true; } }
public static void Main(string[] arguments) { // If executed from JumpTask, do nothing. if (TaskbarHelper.IsJumpTask(arguments)) { return; } // Parse boostrap mode. Mode mode; Enum.TryParse <Mode>(Environment.GetEnvironmentVariable(ModeEnvironmentVariableName), false, out mode); // Parse original PID. int pid; int.TryParse(Environment.GetEnvironmentVariable(PIDEnvironmentVariableName), out pid); switch (mode) { case Mode.RESTART: // Wait for original process to exit. try { Process wait = Process.GetProcessById(pid); if (wait != null) { // If process didn't exit after 10s, bail out. if (!wait.WaitForExit(10000)) { return; } } } catch (ArgumentException) { } // Process doesn't exist, continue. goto default; // Fall-through. default: Run(); break; } }
public void ExecutablesPinnedToTaskbarShouldPointToNewVersion() { string tempDir; using (Utility.WithTempDirectory(out tempDir)) { string packagesDir = Path.Combine(tempDir, "theApp", "packages"); Directory.CreateDirectory(packagesDir); new[] { "SampleUpdatingApp.1.0.0.0.nupkg", "SampleUpdatingApp.1.1.0.0.nupkg", }.ForEach(x => File.Copy(IntegrationTestHelper.GetPath("fixtures", x), Path.Combine(packagesDir, x))); var fixture = new UpdateManager("http://lol", "theApp", FrameworkVersion.Net40, tempDir, null, new FakeUrlDownloader()); var baseEntry = ReleaseEntry.GenerateFromFile(Path.Combine(packagesDir, "SampleUpdatingApp.1.0.0.0.nupkg")); var latestFullEntry = ReleaseEntry.GenerateFromFile(Path.Combine(packagesDir, "SampleUpdatingApp.1.1.0.0.nupkg")); var updateInfo = UpdateInfo.Create(null, new[] { baseEntry }, packagesDir, FrameworkVersion.Net40); using (fixture) { fixture.ApplyReleases(updateInfo).ToList().First(); } var oldExecutable = Path.Combine(tempDir, "theApp", "app-1.0.0.0", "SampleUpdatingApp.exe"); File.Exists(oldExecutable).ShouldBeTrue(); TaskbarHelper.PinToTaskbar(oldExecutable); updateInfo = UpdateInfo.Create(baseEntry, new[] { latestFullEntry }, packagesDir, FrameworkVersion.Net40); using (fixture) { fixture.ApplyReleases(updateInfo).ToList().First(); } var newExecutable = Path.Combine(tempDir, "theApp", "app-1.1.0.0", "SampleUpdatingApp.exe"); File.Exists(newExecutable).ShouldBeTrue(); TaskbarHelper.IsPinnedToTaskbar(newExecutable).ShouldBeTrue(); Utility.Retry(() => TaskbarHelper.UnpinFromTaskbar(newExecutable)); } }
public MainForm() { TaskbarHelper.InitDemoJumpList(TaskbarAssistant.Default, this); AppHelper.MainForm = this; DevExpress.DevAV.StartUpProcess.OnStart("When Only the Best Will Do"); InitializeComponent(); DevExpress.DevAV.StartUpProcess.OnRunning("Initializing..."); Icon = AppHelper.AppIcon; mvvmContext.ViewModelConstructorParameter = this; ViewModel.ModuleAdded += viewModel_ModuleAdded; ViewModel.ModuleRemoved += viewModel_ModuleRemoved; ViewModel.SelectedModuleTypeChanged += viewModel_SelectedModuleTypeChanged; ViewModel.Print += viewModel_Print; ViewModel.ShowAllFolders += viewModel_ShowAllFolders; ViewModel.IsReadingModeChanged += viewModel_IsReadingModeChanged; ribbonControl.MinimizedChanged += Ribbon_MinimizedChanged; ribbonControl.Manager.HideBarsWhenMerging = false; ribbonStatusBar1.HideWhenMerging = DefaultBoolean.False; ribbonControl.ForceInitialize(); new ZoomLevelManager(beZoomLevel, bbiZoomDialog, ViewModel); officeNavigationBar.SynchronizeNavigationClientSelectedItem += officeNavigationBar_SynchronizeNavigationClientSelectedItem; officeNavigationBar.QueryPeekFormContent += officeNavigationBar_QueryPeekFormContent; officeNavigationBar.PopupMenuShowing += officeNavigationBar_PopupMenuShowing; navBar.ActiveGroupChanged += navBar_ActiveGroupChanged; backstageViewControl.SelectedTabChanged += backstageViewControl_SelectedTabChanged; backstageViewControl.Shown += backstageViewControl_Shown; backstageViewControl.Hidden += backstageViewControl_Hidden; backstageViewControl.Office2013StyleOptions.HeaderBackColor = ColorHelper.GetControlColor(LookAndFeel); backstageViewControl.BackstageViewShowRibbonItems = BackstageViewShowRibbonItems.None; // BindCommands(); BindFiltersVisibility(); InitNotifications(); InitTaskBarCommands(); LookAndFeel.StyleChanged += LookAndFeel_StyleChanged; DevExpress.Utils.About.UAlgo.Default.DoEventObject(DevExpress.Utils.About.UAlgo.kDemo, DevExpress.Utils.About.UAlgo.pWinForms, new OutlookInspiredAppWin()); //DEMO_REMOVE this.outlookBehavior = new OutlookReadingModeBehavior(navBar, officeNavigationBar); }
/// <summary> /// Starts preparing a mod by launching a background thread. This should be called from a UI thread /// </summary> private void StartPreparingModWrapper() { NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"UpdaterServiceUpload"); nbw.WorkerReportsProgress = true; nbw.ProgressChanged += (a, b) => { if (b.UserState is double d) { TaskbarHelper.SetProgress(d); } else if (b.UserState is TaskbarItemProgressState tbs) { TaskbarHelper.SetProgressState(tbs); } }; nbw.DoWork += (a, b) => { OperationInProgress = true; b.Result = UploadMod(d => nbw.ReportProgress(0, d), s => nbw.ReportProgress(0, s)); }; nbw.RunWorkerCompleted += (a, b) => { if (b.Error != null) { Log.Error($@"Exception occurred in {nbw.Name} thread: {b.Error.Message}"); } TaskbarHelper.SetProgressState(TaskbarItemProgressState.None); Analytics.TrackEvent(@"Uploaded mod to updater service", new Dictionary <string, string>() { { @"Result", b.Result?.ToString() }, { @"Mod", mod.ModName + @" " + mod.ModVersionString } }); OperationInProgress = false; }; nbw.RunWorkerAsync(); }
// Invoked when application is being started up (before MainWindow creation). private void App_Startup(object sender, StartupEventArgs e) { // Set main thread apartment state. Thread.CurrentThread.SetApartmentState(ApartmentState.STA); // Set AppUserModelId of current process. TaskbarHelper.SetAppUserModelId(); // Create Mutex if this is first instance. try { RunningInstanceMutex = Mutex.OpenExisting(RunningInstanceMutexName); } catch (WaitHandleCannotBeOpenedException) { bool created = false; RunningInstanceMutex = new Mutex(false, RunningInstanceMutexName, out created); if (!created) { throw new Exception("Unable to create application mutex"); } } // Load persistent data. try { PrivatePersistentData.LoadPersistentDataFromFile(); } catch (Exception ex) { MessageBox.Show("An error occurred during a load operation.\n\n" + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } // Initialize localization. L10n.Initialize(PrivatePersistentData); }
private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { timer.CurrentTime = 0; TaskbarHelper.SetState(SaiHelper.AppProcess, TaskbarProgressBarState.NoProgress); Properties.Settings.Default.Save(); }
internal async void OnEnded() { ended = true; timer1000.Stop(); timer200.Stop(); if (ownerClosing) { return; } TaskbarHelper.Remove(ProgressBarTotal); if (closing) { return; } if (client.IsChild) { await client.DisconnectAsync(false, false); } if (client.TransferEvent.Items.Length == 0) { if (client.TransferEvent.IsUpload) { AppMessage.Add("Nothing to upload.", MessageType.Warning); } else { AppMessage.Add("Nothing to download.", MessageType.Warning); } this.Close(); return; } ButtonCancel.IsEnabled = false; ButtonCancel.Visibility = Visibility.Collapsed; ButtonSkip.Visibility = Visibility.Hidden; ButtonPause.Visibility = Visibility.Hidden; if (client.TransferEvent.HasErrors) { MiniProgressBar.SetStateColor(ProgressBarExtension.ProgressState.Error); } else { MiniProgressBar.SetStateColor(ProgressBarExtension.ProgressState.Indeterminate); } switch (fishedAction) { case FishedAction.CloseWindow: if (!this.IsActive && !ClientHelper.Owner.IsActive) { ClientHelper.Owner.FlashWindow(3); } this.Close(); return; case FishedAction.CloseApp: AutoShutdownWindow.Initialize(this, false); this.Close(); return; case FishedAction.Shutdown: AutoShutdownWindow.Initialize(this, true); this.Close(); return; } updateCurrentItem(); UpdateProgress(); updateTotalFF(); LabelCurrentRemainsX.Visibility = Visibility.Collapsed; LabelTotalRemainsX.Visibility = Visibility.Collapsed; LabelETA.Visibility = Visibility.Collapsed; if (client.TransferEvent.IsUpload) { this.Title = client.TransferEvent.HasErrors ? AppLanguage.Get("LangTitleUploadFinishedErrors") : AppLanguage.Get("LangTitleUploadDone"); } else { this.Title = client.TransferEvent.HasErrors ? AppLanguage.Get("LangTitleDownloadFinishedErrors") : AppLanguage.Get("LangTitleDownloadDone"); ButtonOpenTarget.Visibility = Visibility.Visible; } ButtonClose.Visibility = Visibility.Visible; ButtonClose.IsDefault = true; ButtonClose.IsCancel = true; ButtonClose.Focus(); }
private void UpdateClassicMod(OnlineContent.ModUpdateInfo ui) { NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"ModUpdaterThread-" + ui.mod.ModName); nbw.WorkerReportsProgress = true; nbw.ProgressChanged += (a, b) => { if (b.UserState is double d) { TaskbarHelper.SetProgress(d); } }; nbw.DoWork += (a, b) => { OperationInProgress = true; ui.UpdateInProgress = true; ui.Indeterminate = false; ui.DownloadButtonText = M3L.GetString(M3L.string_downloading); ui.ProgressChanged += (a, b) => { if (b.totalToDl != 0 && nbw.IsBusy) //? IsBusy needs to be here for some reason or it crashes, like progress comes in late or something. { nbw.ReportProgress(0, b.currentDl * 1.0 / b.totalToDl); } }; bool errorShown = false; void errorCallback(string message) { if (!errorShown) { errorShown = true; Application.Current.Dispatcher.Invoke(delegate { M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_errorOccuredWhileUpdatingXErrorMessage, ui.mod.ModName, message), M3L.GetString(M3L.string_interp_errorUpdatingX, ui.mod.ModName), MessageBoxButton.OK, MessageBoxImage.Error); } ); } } var stagingDirectory = Directory.CreateDirectory(Path.Combine(Utilities.GetTempPath(), Path.GetFileName(ui.mod.ModPath))).FullName; var modUpdated = OnlineContent.UpdateMod(ui, stagingDirectory, errorCallback); ui.UpdateInProgress = false; ui.CanUpdate = !modUpdated; AnyModUpdated |= modUpdated; ui.DownloadButtonText = ui.CanUpdate ? M3L.GetString(M3L.string_downloadUpdate) : M3L.GetString(M3L.string_updated); Utilities.DeleteFilesAndFoldersRecursively(stagingDirectory); }; nbw.RunWorkerCompleted += (a, b) => { if (b.Error != null) { Log.Error($@"Exception occurred in {nbw.Name} thread: {b.Error.Message}"); } Analytics.TrackEvent(@"Updated mod", new Dictionary <string, string>() { { @"Type", @"Classic" }, { @"ModName", ui.mod.ModName }, { @"Result", ui.CanUpdate ? @"Success" : @"Failed" } }); TaskbarHelper.SetProgressState(TaskbarProgressBarState.NoProgress); OperationInProgress = false; CommandManager.InvalidateRequerySuggested(); }; TaskbarHelper.SetProgress(0); TaskbarHelper.SetProgressState(TaskbarProgressBarState.Normal); nbw.RunWorkerAsync(); }
private void BeginBackup() { var targetToBackup = BackupSourceTarget; if (!targetToBackup.IsCustomOption) { if (Utilities.IsGameRunning(targetToBackup.Game)) { M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_cannotBackupGameWhileRunning, Utilities.GetGameName(BackupSourceTarget.Game)), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error); return; } } else { // Point to existing game installation Log.Information(@"BeginBackup() with IsCustomOption."); var linkWarning = M3L.ShowDialog(window, M3L.GetString(M3L.string_dialog_linkTargetWontBeModdable), M3L.GetString(M3L.string_linkWarning), MessageBoxButton.OKCancel, MessageBoxImage.Warning); if (linkWarning == MessageBoxResult.Cancel) { Log.Information(@"User aborted linking due to dialog"); return; } Log.Information(@"Prompting user to select executable of link target"); var gameexe = Utilities.PromptForGameExecutable(new[] { Game }); if (gameexe == null) { return; } targetToBackup = new GameTarget(Game, Utilities.GetGamePathFromExe(Game, gameexe), false, true); if (AvailableBackupSources.Any(x => x.TargetPath.Equals(targetToBackup.TargetPath, StringComparison.InvariantCultureIgnoreCase))) { // Can't point to an existing modding target Log.Error(@"This target is not valid to point to as a backup: It is listed a modding target already, it must be removed as a target first"); M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_dialog_linkFailedAlreadyATarget), M3L.GetString(M3L.string_cannotLinkGameCopy), MessageBoxButton.OK, MessageBoxImage.Error); return; } var validationFailureReason = targetToBackup.ValidateTarget(ignoreCmmVanilla: true); if (!targetToBackup.IsValid) { Log.Error(@"This installation is not valid to point to as a backup: " + validationFailureReason); M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_dialog_linkFailedInvalidTarget, validationFailureReason), M3L.GetString(M3L.string_invalidGameCopy), MessageBoxButton.OK, MessageBoxImage.Error); return; } } NamedBackgroundWorker nbw = new NamedBackgroundWorker(Game + @"Backup"); nbw.WorkerReportsProgress = true; nbw.ProgressChanged += (a, b) => { if (b.UserState is double d) { TaskbarHelper.SetProgress(d); } else if (b.UserState is TaskbarProgressBarState tbs) { TaskbarHelper.SetProgressState(tbs); } }; nbw.DoWork += (a, b) => { Log.Information(@"Starting the backup thread. Checking path: " + targetToBackup.TargetPath); BackupInProgress = true; bool end = false; List <string> nonVanillaFiles = new List <string>(); void nonVanillaFileFoundCallback(string filepath) { Log.Error($@"Non-vanilla file found: {filepath}"); nonVanillaFiles.Add(filepath); } List <string> inconsistentDLC = new List <string>(); void inconsistentDLCFoundCallback(string filepath) { if (targetToBackup.Supported) { Log.Error($@"DLC is in an inconsistent state: {filepath}"); inconsistentDLC.Add(filepath); } else { Log.Error(@"Detected an inconsistent DLC, likely due to an unofficial copy of the game"); } } ProgressVisible = true; ProgressIndeterminate = true; BackupStatus = M3L.GetString(M3L.string_validatingBackupSource); Log.Information(@"Checking target is vanilla"); bool isVanilla = VanillaDatabaseService.ValidateTargetAgainstVanilla(targetToBackup, nonVanillaFileFoundCallback); Log.Information(@"Checking DLC consistency"); bool isDLCConsistent = VanillaDatabaseService.ValidateTargetDLCConsistency(targetToBackup, inconsistentDLCCallback: inconsistentDLCFoundCallback); Log.Information(@"Checking only vanilla DLC is installed"); List <string> dlcModsInstalled = VanillaDatabaseService.GetInstalledDLCMods(targetToBackup).Select(x => { var tpmi = ThirdPartyServices.GetThirdPartyModInfo(x, targetToBackup.Game); if (tpmi != null) { return($@"{x} ({tpmi.modname})"); } return(x); }).ToList(); var installedDLC = VanillaDatabaseService.GetInstalledOfficialDLC(targetToBackup); var allOfficialDLC = MEDirectories.OfficialDLC(targetToBackup.Game); if (installedDLC.Count() < allOfficialDLC.Count()) { var dlcList = string.Join("\n - ", allOfficialDLC.Except(installedDLC).Select(x => $@"{MEDirectories.OfficialDLCNames(targetToBackup.Game)[x]} ({x})")); //do not localize dlcList = @" - " + dlcList; Log.Information(@"The following dlc will be missing in the backup if user continues: "); Log.Information(dlcList); Application.Current.Dispatcher.Invoke(delegate { var cancelDueToNotAllDLC = M3L.ShowDialog(window, M3L.GetString(M3L.string_dialog_notAllDLCInstalled, dlcList), M3L.GetString(M3L.string_someDlcNotInstalled), MessageBoxButton.YesNo, MessageBoxImage.Warning); if (cancelDueToNotAllDLC == MessageBoxResult.No) { end = true; EndBackup(); return; } }); } Log.Information(@"Checking for TexturesMEM TFCs"); var memTextures = Directory.GetFiles(targetToBackup.TargetPath, @"TexturesMEM*.tfc", SearchOption.AllDirectories); if (end) { return; } if (isVanilla && isDLCConsistent && !Enumerable.Any(dlcModsInstalled) && !Enumerable.Any(memTextures)) { BackupStatus = M3L.GetString(M3L.string_waitingForUserInput); string backupPath = null; if (!targetToBackup.IsCustomOption) { // Creating a new backup nbw.ReportProgress(0, TaskbarProgressBarState.Paused); Application.Current.Dispatcher.Invoke(delegate { Log.Information(@"Prompting user to select backup destination"); CommonOpenFileDialog m = new CommonOpenFileDialog { IsFolderPicker = true, EnsurePathExists = true, Title = M3L.GetString(M3L.string_selectBackupDestination) }; if (m.ShowDialog() == CommonFileDialogResult.Ok) { backupPath = m.FileName; Log.Information(@"Backup path chosen: " + backupPath); bool okToBackup = validateBackupPath(backupPath, targetToBackup); if (!okToBackup) { end = true; EndBackup(); return; } } else { end = true; EndBackup(); return; } }); if (end) { return; } nbw.ReportProgress(0, TaskbarProgressBarState.Indeterminate); } else { Log.Information(@"Linking existing backup at " + targetToBackup.TargetPath); backupPath = targetToBackup.TargetPath; // Linking existing backup Application.Current.Dispatcher.Invoke(delegate { bool okToBackup = validateBackupPath(targetToBackup.TargetPath, targetToBackup); if (!okToBackup) { end = true; EndBackup(); return; } }); } if (end) { return; } if (!targetToBackup.IsCustomOption) { #region callbacks and copy code // Copy to new backup void fileCopiedCallback() { ProgressValue++; if (ProgressMax > 0) { nbw.ReportProgress(0, ProgressValue * 1.0 / ProgressMax); } } string dlcFolderpath = M3Directories.GetDLCPath(targetToBackup) + '\\'; int dlcSubStringLen = dlcFolderpath.Length; bool aboutToCopyCallback(string file) { try { if (file.Contains(@"\cmmbackup\")) { return(false); //do not copy cmmbackup files } if (file.StartsWith(dlcFolderpath, StringComparison.InvariantCultureIgnoreCase)) { //It's a DLC! string dlcname = file.Substring(dlcSubStringLen); var dlcFolderNameEndPos = dlcname.IndexOf('\\'); if (dlcFolderNameEndPos > 0) { dlcname = dlcname.Substring(0, dlcFolderNameEndPos); if (MEDirectories.OfficialDLCNames(targetToBackup.Game) .TryGetValue(dlcname, out var hrName)) { BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, hrName); } else { BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, dlcname); } } else { // Loose files in the DLC folder BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, M3L.GetString(M3L.string_basegame)); } } else { //It's basegame if (file.EndsWith(@".bik")) { BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, M3L.GetString(M3L.string_movies)); } else if (new FileInfo(file).Length > 52428800) { BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, Path.GetFileName(file)); } else { BackupStatusLine2 = M3L.GetString(M3L.string_interp_backingUpX, M3L.GetString(M3L.string_basegame)); } } } catch (Exception e) { Crashes.TrackError(e, new Dictionary <string, string>() { { @"dlcFolderpath", dlcFolderpath }, { @"dlcSubStringLen", dlcSubStringLen.ToString() }, { @"file", file } }); } return(true); } void totalFilesToCopyCallback(int total) { ProgressValue = 0; ProgressIndeterminate = false; ProgressMax = total; nbw.ReportProgress(0, TaskbarProgressBarState.Normal); } BackupStatus = M3L.GetString(M3L.string_creatingBackup); Log.Information($@"Backing up {targetToBackup.TargetPath} to {backupPath}"); nbw.ReportProgress(0, TaskbarProgressBarState.Normal); CopyDir.CopyAll_ProgressBar(new DirectoryInfo(targetToBackup.TargetPath), new DirectoryInfo(backupPath), totalItemsToCopyCallback: totalFilesToCopyCallback, aboutToCopyCallback: aboutToCopyCallback, fileCopiedCallback: fileCopiedCallback, ignoredExtensions: new[] { @"*.pdf", @"*.mp3" }); #endregion } // Write key switch (Game) { case MEGame.ME1: case MEGame.ME2: Utilities.WriteRegistryKey(App.BACKUP_REGISTRY_KEY, Game + @"VanillaBackupLocation", backupPath); break; case MEGame.ME3: Utilities.WriteRegistryKey(App.REGISTRY_KEY_ME3CMM, @"VanillaCopyLocation", backupPath); break; } var cmmvanilla = Path.Combine(backupPath, @"cmm_vanilla"); if (!File.Exists(cmmvanilla)) { Log.Information($@"Writing cmm_vanilla to " + cmmvanilla); File.Create(cmmvanilla).Close(); } Log.Information($@"Backup completed."); Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Success" }, { @"Type", targetToBackup.IsCustomOption ? @"Linked" : @"Copy" } }); EndBackup(); return; } if (!isVanilla) { //Show UI for non vanilla Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, Game modified" } }); b.Result = (nonVanillaFiles, M3L.GetString(M3L.string_cannotBackupModifiedGame), M3L.GetString(M3L.string_followingFilesDoNotMatchTheVanillaDatabase)); } else if (!isDLCConsistent) { Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, DLC inconsistent" } }); if (targetToBackup.Supported) { b.Result = (inconsistentDLC, M3L.GetString(M3L.string_inconsistentDLCDetected), M3L.GetString(M3L.string_dialogTheFollowingDLCAreInAnInconsistentState)); } else { b.Result = (M3L.GetString(M3L.string_inconsistentDLCDetected), M3L.GetString(M3L.string_inconsistentDLCDetectedUnofficialGame)); } } else if (Enumerable.Any(dlcModsInstalled)) { Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, DLC mods found" } }); b.Result = (dlcModsInstalled, M3L.GetString(M3L.string_dlcModsAreInstalled), M3L.GetString(M3L.string_dialogDLCModsWereDetectedCannotBackup)); } else if (Enumerable.Any(memTextures)) { Analytics.TrackEvent(@"Created a backup", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, TexturesMEM files found" } }); b.Result = (M3L.GetString(M3L.string_leftoverTextureFilesFound), M3L.GetString(M3L.string_dialog_foundLeftoverTextureFiles)); } EndBackup(); }; nbw.RunWorkerCompleted += (a, b) => { if (b.Error != null) { Log.Error($@"Exception occurred in {nbw.Name} thread: {b.Error.Message}"); } TaskbarHelper.SetProgressState(TaskbarProgressBarState.NoProgress); if (b.Result is (List <string> listItems, string title, string text)) { ListDialog ld = new ListDialog(listItems, title, text, window); ld.Show(); } else if (b.Result is (string errortitle, string message)) { M3L.ShowDialog(window, message, errortitle, MessageBoxButton.OK, MessageBoxImage.Error); } CommandManager.InvalidateRequerySuggested(); }; nbw.RunWorkerAsync(); }
private void BeginRestore() { if (Utilities.IsGameRunning(Game)) { M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_dialogCannotRestoreXWhileItIsRunning, Utilities.GetGameName(Game)), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error); return; } bool restore = RestoreTarget.IsCustomOption; //custom option is restore to custom location restore = restore || M3L.ShowDialog(window, M3L.GetString(M3L.string_dialog_restoringXWillDeleteGameDir, Utilities.GetGameName(Game)), M3L.GetString(M3L.string_gameTargetWillBeDeleted), MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes; if (restore) { NamedBackgroundWorker nbw = new NamedBackgroundWorker(Game + @"-Restore"); nbw.WorkerReportsProgress = true; nbw.ProgressChanged += (a, b) => { if (b.UserState is double d) { TaskbarHelper.SetProgress(d); } }; nbw.DoWork += (a, b) => { RestoreInProgress = true; string restoreTargetPath = b.Argument as string; string backupPath = BackupLocation; BackupStatusLine2 = M3L.GetString(M3L.string_deletingExistingGameInstallation); if (Directory.Exists(restoreTargetPath)) { if (Directory.GetFiles(restoreTargetPath).Any() || Directory.GetDirectories(restoreTargetPath).Any()) { Log.Information(@"Deleting existing game directory: " + restoreTargetPath); try { bool deletedDirectory = Utilities.DeleteFilesAndFoldersRecursively(restoreTargetPath); if (deletedDirectory != true) { b.Result = RestoreResult.ERROR_COULD_NOT_DELETE_GAME_DIRECTORY; return; } } catch (Exception ex) { //todo: handle this better Log.Error($@"Exception deleting game directory: {restoreTargetPath}: {ex.Message}"); b.Result = RestoreResult.EXCEPTION_DELETING_GAME_DIRECTORY; return; } } } else { Log.Error(@"Game directory not found! Was it removed while the app was running?"); } //Todo: Revert LODs, remove IndirectSound settings (MEUITM) var created = Utilities.CreateDirectoryWithWritePermission(restoreTargetPath); if (!created) { b.Result = RestoreResult.ERROR_COULD_NOT_CREATE_DIRECTORY; return; } BackupStatusLine2 = M3L.GetString(M3L.string_restoringGameFromBackup); if (restoreTargetPath != null) { //callbacks #region callbacks void fileCopiedCallback() { ProgressValue++; if (ProgressMax != 0) { nbw.ReportProgress(0, ProgressValue * 1.0 / ProgressMax); } } string dlcFolderpath = MEDirectories.DLCPath(backupPath, Game) + '\\'; //\ at end makes sure we are restoring a subdir int dlcSubStringLen = dlcFolderpath.Length; Debug.WriteLine(@"DLC Folder: " + dlcFolderpath); Debug.Write(@"DLC Fodler path len:" + dlcFolderpath); bool aboutToCopyCallback(string fileBeingCopied) { if (fileBeingCopied.Contains(@"\cmmbackup\")) { return(false); //do not copy cmmbackup files } Debug.WriteLine(fileBeingCopied); if (fileBeingCopied.StartsWith(dlcFolderpath, StringComparison.InvariantCultureIgnoreCase)) { //It's a DLC! string dlcname = fileBeingCopied.Substring(dlcSubStringLen); int index = dlcname.IndexOf('\\'); try { dlcname = dlcname.Substring(0, index); if (MEDirectories.OfficialDLCNames(RestoreTarget.Game).TryGetValue(dlcname, out var hrName)) { BackupStatusLine2 = M3L.GetString(M3L.string_interp_restoringX, hrName); } else { BackupStatusLine2 = M3L.GetString(M3L.string_interp_restoringX, dlcname); } } catch (Exception e) { Crashes.TrackError(e, new Dictionary <string, string>() { { @"Source", @"Restore UI display callback" }, { @"Value", fileBeingCopied }, { @"DLC Folder path", dlcFolderpath } }); } } else { //It's basegame if (fileBeingCopied.EndsWith(@".bik")) { BackupStatusLine2 = M3L.GetString(M3L.string_restoringMovies); } else if (new FileInfo(fileBeingCopied).Length > 52428800) { BackupStatusLine2 = M3L.GetString(M3L.string_interp_restoringX, Path.GetFileName(fileBeingCopied)); } else { BackupStatusLine2 = M3L.GetString(M3L.string_restoringBasegame); } } return(true); } void totalFilesToCopyCallback(int total) { ProgressValue = 0; ProgressIndeterminate = false; ProgressMax = total; } #endregion BackupStatus = M3L.GetString(M3L.string_restoringGame); Log.Information($@"Copying backup to game directory: {backupPath} -> {restoreTargetPath}"); CopyDir.CopyAll_ProgressBar(new DirectoryInfo(backupPath), new DirectoryInfo(restoreTargetPath), totalItemsToCopyCallback: totalFilesToCopyCallback, aboutToCopyCallback: aboutToCopyCallback, fileCopiedCallback: fileCopiedCallback, ignoredExtensions: new[] { @"*.pdf", @"*.mp3" }); Log.Information(@"Restore of game data has completed"); } //Check for cmmvanilla file and remove it present string cmmVanilla = Path.Combine(restoreTargetPath, @"cmm_vanilla"); if (File.Exists(cmmVanilla)) { Log.Information(@"Removing cmm_vanilla file"); File.Delete(cmmVanilla); } Log.Information(@"Restore thread wrapping up"); RestoreTarget.ReloadGameTarget(); b.Result = RestoreResult.RESTORE_OK; }; nbw.RunWorkerCompleted += (a, b) => { if (b.Error != null) { Log.Error($@"Exception occurred in {nbw.Name} thread: {b.Error.Message}"); } TaskbarHelper.SetProgressState(TaskbarProgressBarState.NoProgress); if (b.Result is RestoreResult result) { switch (result) { case RestoreResult.ERROR_COULD_NOT_CREATE_DIRECTORY: Analytics.TrackEvent(@"Restored game", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, Could not create target directory" } }); M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogCouldNotCreateGameDirectoryAfterDeletion), M3L.GetString(M3L.string_errorRestoringGame), MessageBoxButton.OK, MessageBoxImage.Error); break; case RestoreResult.ERROR_COULD_NOT_DELETE_GAME_DIRECTORY: Analytics.TrackEvent(@"Restored game", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, Could not delete existing game directory" } }); M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogcouldNotFullyDeleteGameDirectory), M3L.GetString(M3L.string_errorRestoringGame), MessageBoxButton.OK, MessageBoxImage.Error); break; case RestoreResult.EXCEPTION_DELETING_GAME_DIRECTORY: Analytics.TrackEvent(@"Restored game", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, Exception deleting existing game directory" } }); M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogErrorOccuredDeletingGameDirectory), M3L.GetString(M3L.string_errorRestoringGame), MessageBoxButton.OK, MessageBoxImage.Error); break; case RestoreResult.RESTORE_OK: Analytics.TrackEvent(@"Restored game", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Success" } }); break; } } EndRestore(); CommandManager.InvalidateRequerySuggested(); }; var restTarget = RestoreTarget.TargetPath; if (RestoreTarget.IsCustomOption) { CommonOpenFileDialog m = new CommonOpenFileDialog { IsFolderPicker = true, EnsurePathExists = true, Title = M3L.GetString(M3L.string_selectNewRestoreDestination) }; if (m.ShowDialog() == CommonFileDialogResult.Ok) { //Check empty restTarget = m.FileName; if (Directory.Exists(restTarget)) { if (Directory.GetFiles(restTarget).Length > 0 || Directory.GetDirectories(restTarget).Length > 0) { //Directory not empty M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogDirectoryIsNotEmptyLocationToRestoreToMustBeEmpty), M3L.GetString(M3L.string_cannotRestoreToThisLocation), MessageBoxButton.OK, MessageBoxImage.Error); return; } //TODO: PREVENT RESTORING TO DOCUMENTS/BIOWARE } Analytics.TrackEvent(@"Chose to restore game to custom location", new Dictionary <string, string>() { { @"Game", Game.ToString() } }); } else { return; } } RefreshTargets = true; TaskbarHelper.SetProgress(0); TaskbarHelper.SetProgressState(TaskbarProgressBarState.Normal); nbw.RunWorkerAsync(restTarget); } }
private void Timer_OnProgress(object sender, int e) { Threading.ComponentInvoke(progressBar1, (x) => x.Value = e); TaskbarHelper.SetProgress(SaiHelper.AppProcess, e, progressBar1.Maximum); }
private void UpdateModMakerMod(OnlineContent.ModMakerModUpdateInfo mui) { //throw new NotImplementedException(); NamedBackgroundWorker nbw = new NamedBackgroundWorker(@"ModmakerModUpdaterThread-" + mui.mod.ModName); nbw.WorkerReportsProgress = true; nbw.ProgressChanged += (a, b) => { if (b.UserState is double d) { TaskbarHelper.SetProgress(d); } }; nbw.DoWork += (a, b) => { mui.DownloadButtonText = M3L.GetString(M3L.string_compiling); OperationInProgress = true; mui.UpdateInProgress = true; mui.Indeterminate = false; mui.UIStatusString = M3L.GetString(M3L.string_downloadingDelta); var normalEndpoint = OnlineContent.ModmakerModsEndpoint + mui.ModMakerId; var lzmaEndpoint = normalEndpoint + @"&method=lzma"; string modDelta = null; //Try LZMA first try { var download = OnlineContent.DownloadToMemory(lzmaEndpoint); if (download.errorMessage == null) { mui.UIStatusString = M3L.GetString(M3L.string_decompressingDelta); // OK var decompressed = SevenZipHelper.LZMA.DecompressLZMAFile(download.result.ToArray()); modDelta = Encoding.UTF8.GetString(decompressed); } else { Log.Error(@"Error downloading lzma mod delta to memory: " + download.errorMessage); } } catch (Exception e) { Log.Error(@"Error downloading LZMA mod delta to memory: " + e.Message); } if (modDelta == null) { //failed to download LZMA. var download = OnlineContent.DownloadToMemory(normalEndpoint); if (download.errorMessage == null) { //OK modDelta = Encoding.UTF8.GetString(download.result.ToArray()); } else { Log.Error(@"Error downloading decompressed mod delta to memory: " + download.errorMessage); } } void setOverallMax(int max) { mui.OverallProgressMax = max; } void setOverallValue(int current) { mui.OverallProgressValue = current; nbw.ReportProgress(0, current * 1.0 / mui.OverallProgressMax); if (current > mui.OverallProgressMax) { Debugger.Break(); } } void setCurrentTaskString(string str) { mui.UIStatusString = str; } if (modDelta != null) { var compiler = new ModMakerCompiler(mui.ModMakerId); //compiler.SetCurrentMaxCallback = SetCurrentMax; //compiler.SetCurrentValueCallback = SetCurrentProgressValue; compiler.SetOverallMaxCallback = setOverallMax; compiler.SetOverallValueCallback = setOverallValue; //compiler.SetCurrentTaskIndeterminateCallback = SetCurrentTaskIndeterminate; compiler.SetCurrentTaskStringCallback = setCurrentTaskString; //compiler.SetModNameCallback = SetModNameOrDownloadText; //compiler.SetCompileStarted = CompilationInProgress; //compiler.SetModNotFoundCallback = ModNotFound; Mod m = compiler.DownloadAndCompileMod(modDelta); if (m != null) { try { File.WriteAllText(System.IO.Path.Combine(Utilities.GetModmakerDefinitionsCache(), mui.ModMakerId + @".xml"), modDelta); } catch (Exception e) { Log.Error(@"Couldn't cache modmaker xml file: " + e.Message); } mui.DownloadButtonText = M3L.GetString(M3L.string_updated); mui.UIStatusString = M3L.GetString(M3L.string_interp_modMakerCodeX, mui.ModMakerId); mui.UpdateInProgress = false; mui.CanUpdate = false; AnyModUpdated = true; } else { mui.UpdateInProgress = false; mui.DownloadButtonText = M3L.GetString(M3L.string_compilingFailed); mui.UpdateInProgress = false; } } }; nbw.RunWorkerCompleted += (a, b) => { if (b.Error != null) { Log.Error($@"Exception occurred in {nbw.Name} thread: {b.Error.Message}"); } Analytics.TrackEvent(@"Updated mod", new Dictionary <string, string>() { { @"Type", @"ModMaker" }, { @"ModName", mui.mod.ModName }, { @"Result", mui.CanUpdate ? @"Success" : @"Failed" } }); TaskbarHelper.SetProgressState(TaskbarProgressBarState.NoProgress); OperationInProgress = false; CommandManager.InvalidateRequerySuggested(); }; TaskbarHelper.SetProgress(0); TaskbarHelper.SetProgressState(TaskbarProgressBarState.Normal); nbw.RunWorkerAsync(); }
public static async void StartRestore(MainWindow mw, bool isQuick, Action postRestoreDelegate = null) { var pd = await mw.ShowProgressAsync("Restoring game", "Preparing to restore game"); pd.SetIndeterminate(); await Task.Run(() => { if (isQuick) { // Nuke the DLC MERLog.Information(@"Quick restore started"); pd.SetMessage("Removing randomize DLC component"); var dlcModPath = MERFileSystem.GetDLCModPath(); if (Directory.Exists(dlcModPath)) { MERLog.Information($@"Deleting {dlcModPath}"); Utilities.DeleteFilesAndFoldersRecursively(dlcModPath); } mw.DLCComponentInstalled = false; // Restore basegame only files pd.SetMessage("Restoring randomized basegame files"); var isControllerModInstalled = SFXGame.IsControllerBasedInstall(); var backupPath = BackupService.GetGameBackupPath(MERFileSystem.Game, out _, false); var gameCookedPath = M3Directories.GetCookedPath(Locations.GetTarget(MERFileSystem.Game)); var backupCookedPath = MEDirectories.GetCookedPath(MERFileSystem.Game, backupPath); foreach (var bgf in MERFileSystem.alwaysBasegameFiles) { var srcPath = Path.Combine(backupCookedPath, bgf); var destPath = Path.Combine(gameCookedPath, bgf); MERLog.Information($@"Restoring {bgf}"); File.Copy(srcPath, destPath, true); } if (isControllerModInstalled) { // We must also restore Coalesced.ini or it will reference a UI that is no longer available and game will not boot MERLog.Information(@"Controller based install detected, also restoring Coalesced.ini to prevent startup crash"); File.Copy(Path.Combine(backupPath, "BioGame", "Config", "PC", "Cooked", "Coalesced.ini"), Path.Combine(Locations.GetTarget(MERFileSystem.Game).TargetPath, "BioGame", "Config", "PC", "Cooked", "Coalesced.ini"), true); } // Delete basegame TFC var baseTFC = MERFileSystem.GetTFCPath(false); if (File.Exists(baseTFC)) { File.Delete(baseTFC); } // Done! } else { // Full restore var target = Locations.GetTarget(MERFileSystem.Game); MERLog.Information($@"Performing full game restore on {target.TargetPath} target after restore"); object syncObj = new object(); BackupHandler.GameRestore gr = new BackupHandler.GameRestore(MERFileSystem.Game) { ConfirmationCallback = (title, message) => { bool response = false; Application.Current.Dispatcher.Invoke(async() => { response = await mw.ShowMessageAsync(title, message, MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings() { AffirmativeButtonText = "OK", NegativeButtonText = "Cancel", }) == MessageDialogResult.Affirmative; lock (syncObj) { Monitor.Pulse(syncObj); } }); lock (syncObj) { Monitor.Wait(syncObj); } return(response); }, BlockingErrorCallback = (title, message) => { Application.Current.Dispatcher.Invoke(async() => { await mw.ShowMessageAsync(title, message); }); }, RestoreErrorCallback = (title, message) => { Application.Current.Dispatcher.Invoke(async() => { await mw.ShowMessageAsync(title, message); }); }, UpdateStatusCallback = message => Application.Current.Dispatcher.Invoke(() => pd.SetMessage(message)), UpdateProgressCallback = (done, total) => Application.Current.Dispatcher.Invoke(() => { pd.SetProgress(done * 1d / total); if (total != 0) { TaskbarHelper.SetProgressState(TaskbarProgressBarState.Normal); TaskbarHelper.SetProgress(done * 1.0 / total); } }), SetProgressIndeterminateCallback = indeterminate => Application.Current.Dispatcher.Invoke(() => { if (indeterminate) { pd.SetIndeterminate(); } TaskbarHelper.SetProgressState(indeterminate ? TaskbarProgressBarState.Indeterminate : TaskbarProgressBarState.Normal); }), SelectDestinationDirectoryCallback = (title, message) => { string selectedPath = null; Application.Current.Dispatcher.Invoke(() => { // Not sure if this has to be synced CommonOpenFileDialog ofd = new CommonOpenFileDialog() { Title = "Select restore destination directory", IsFolderPicker = true, EnsurePathExists = true }; if (ofd.ShowDialog() == CommonFileDialogResult.Ok) { selectedPath = ofd.FileName; } }); return(selectedPath); } }; gr.PerformRestore(target.TargetPath); mw.DLCComponentInstalled = false; MERLog.Information(@"Reloading target after restore"); target.ReloadGameTarget(false, false); mw.SetupTargetDescriptionText(); } }).ContinueWithOnUIThread(async x => { TaskbarHelper.SetProgressState(TaskbarProgressBarState.NoProgress); await pd.CloseAsync(); postRestoreDelegate?.Invoke(); }); }
private void BeginRestore() { if (Utilities.IsGameRunning(Game)) { M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_dialogCannotRestoreXWhileItIsRunning, Game.ToGameName()), M3L.GetString(M3L.string_gameRunning), MessageBoxButton.OK, MessageBoxImage.Error); return; } var useNewMethod = M3L.ShowDialog(window, M3L.GetString(M3L.string_beta_useNewRestoreMethod), M3L.GetString(M3L.string_useBetaFeatureQuestion), MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes; bool restore = RestoreTarget.IsCustomOption || useNewMethod; //custom option is restore to custom location restore = restore || M3L.ShowDialog(window, M3L.GetString(M3L.string_dialog_restoringXWillDeleteGameDir, Game.ToGameName()), M3L.GetString(M3L.string_gameTargetWillBeDeleted), MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes; if (restore) { NamedBackgroundWorker nbw = new NamedBackgroundWorker(Game + @"-Restore"); nbw.WorkerReportsProgress = true; nbw.ProgressChanged += (a, b) => { if (b.UserState is double d) { TaskbarHelper.SetProgress(d); } }; nbw.DoWork += (a, b) => { RestoreInProgress = true; // Nuke the LODs if (!RestoreTarget.IsCustomOption && RestoreTarget.Game.IsOTGame()) { Log.Information($@"Resetting LODs for {RestoreTarget.Game}"); Utilities.SetLODs(RestoreTarget, false, false, false); } string restoreTargetPath = b.Argument as string; string backupPath = BackupLocation; if (!useNewMethod) { BackupStatusLine2 = M3L.GetString(M3L.string_deletingExistingGameInstallation); if (Directory.Exists(restoreTargetPath)) { if (Directory.GetFiles(restoreTargetPath).Any() || Directory.GetDirectories(restoreTargetPath).Any()) { Log.Information(@"Deleting existing game directory: " + restoreTargetPath); try { bool deletedDirectory = Utilities.DeleteFilesAndFoldersRecursively(restoreTargetPath); if (deletedDirectory != true) { b.Result = RestoreResult.ERROR_COULD_NOT_DELETE_GAME_DIRECTORY; return; } } catch (Exception ex) { //todo: handle this better Log.Error( $@"Exception deleting game directory: {restoreTargetPath}: {ex.Message}"); b.Result = RestoreResult.EXCEPTION_DELETING_GAME_DIRECTORY; return; } } } else { Log.Error(@"Game directory not found! Was it removed while the app was running?"); } var created = Utilities.CreateDirectoryWithWritePermission(restoreTargetPath); if (!created) { b.Result = RestoreResult.ERROR_COULD_NOT_CREATE_DIRECTORY; return; } } BackupStatusLine2 = M3L.GetString(M3L.string_restoringGameFromBackup); if (restoreTargetPath != null) { //callbacks #region callbacks void fileCopiedCallback() { ProgressValue++; if (ProgressMax != 0) { nbw.ReportProgress(0, ProgressValue * 1.0 / ProgressMax); } } string dlcFolderpath = MEDirectories.GetDLCPath(Game, backupPath) + '\\'; //\ at end makes sure we are restoring a subdir int dlcSubStringLen = dlcFolderpath.Length; Debug.WriteLine(@"DLC Folder: " + dlcFolderpath); Debug.Write(@"DLC Folder path len:" + dlcFolderpath); bool aboutToCopyCallback(string fileBeingCopied) { if (fileBeingCopied.Contains(@"\cmmbackup\")) { return(false); //do not copy cmmbackup files } Debug.WriteLine(fileBeingCopied); if (fileBeingCopied.StartsWith(dlcFolderpath, StringComparison.InvariantCultureIgnoreCase)) { //It's a DLC! string dlcname = fileBeingCopied.Substring(dlcSubStringLen); int index = dlcname.IndexOf('\\'); if (index > 0) //Files directly in the DLC directory won't have path sep { try { dlcname = dlcname.Substring(0, index); if (MEDirectories.OfficialDLCNames(RestoreTarget.Game).TryGetValue(dlcname, out var hrName)) { BackupStatusLine2 = M3L.GetString(M3L.string_interp_restoringX, hrName); } else { BackupStatusLine2 = M3L.GetString(M3L.string_interp_restoringX, dlcname); } } catch (Exception e) { Crashes.TrackError(e, new Dictionary <string, string>() { { @"Source", @"Restore UI display callback" }, { @"Value", fileBeingCopied }, { @"DLC Folder path", dlcFolderpath } }); } } } else { //It's basegame if (fileBeingCopied.EndsWith(@".bik")) { BackupStatusLine2 = M3L.GetString(M3L.string_restoringMovies); } else if (new FileInfo(fileBeingCopied).Length > 52428800) { BackupStatusLine2 = M3L.GetString(M3L.string_interp_restoringX, Path.GetFileName(fileBeingCopied)); } else { BackupStatusLine2 = M3L.GetString(M3L.string_restoringBasegame); } } return(true); } void totalFilesToCopyCallback(int total) { ProgressValue = 0; ProgressIndeterminate = false; ProgressMax = total; } #endregion BackupStatus = M3L.GetString(M3L.string_restoringGame); // LE: Backup Config file so settings don't get lost string configText = null; var configPath = RestoreTarget.Game.IsLEGame() ? M3Directories.GetLODConfigFile(RestoreTarget) : null; if (File.Exists(configPath)) { configText = File.ReadAllText(configPath); // backup to memory } Log.Information($@"Copying backup to game directory: {backupPath} -> {restoreTargetPath}"); if (useNewMethod) { string CurrentRCFile = null; RoboCommand rc = new RoboCommand(); rc.CopyOptions.Destination = restoreTargetPath; rc.CopyOptions.Source = backupPath; rc.CopyOptions.Mirror = true; rc.CopyOptions.MultiThreadedCopiesCount = 2; rc.OnCopyProgressChanged += (sender, args) => { ProgressIndeterminate = false; ProgressValue = (int)args.CurrentFileProgress; ProgressMax = 100; }; rc.OnFileProcessed += (sender, args) => { if (args.ProcessedFile.Name.StartsWith(backupPath) && args.ProcessedFile.Name.Length > backupPath.Length) { CurrentRCFile = args.ProcessedFile.Name.Substring(backupPath.Length + 1); BackupStatusLine2 = M3L.GetString(M3L.string_interp_copyingX, CurrentRCFile); } }; rc.Start().Wait(); } else { CopyDir.CopyAll_ProgressBar(new DirectoryInfo(backupPath), new DirectoryInfo(restoreTargetPath), totalItemsToCopyCallback: totalFilesToCopyCallback, aboutToCopyCallback: aboutToCopyCallback, fileCopiedCallback: fileCopiedCallback, ignoredExtensions: new[] { @"*.pdf", @"*.mp3" }); } Log.Information(@"Restore of game data has completed"); if (configText != null) { // Restore config file try { Directory.CreateDirectory(Directory.GetParent(configPath).FullName); File.WriteAllText(configPath, configText); Log.Information(@"Restored config file"); } catch (Exception e) { Log.Error($@"Could not restore config file: {e.Message}"); } } BackupCopyFinished(restoreTargetPath); } }; nbw.RunWorkerCompleted += (a, b) => { if (b.Error != null) { Log.Error($@"Exception occurred in {nbw.Name} thread: {b.Error.Message}"); } TaskbarHelper.SetProgressState(TaskbarProgressBarState.NoProgress); if (b.Result is RestoreResult result) { switch (result) { case RestoreResult.ERROR_COULD_NOT_CREATE_DIRECTORY: Analytics.TrackEvent(@"Restored game", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, Could not create target directory" } }); M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogCouldNotCreateGameDirectoryAfterDeletion), M3L.GetString(M3L.string_errorRestoringGame), MessageBoxButton.OK, MessageBoxImage.Error); break; case RestoreResult.ERROR_COULD_NOT_DELETE_GAME_DIRECTORY: Analytics.TrackEvent(@"Restored game", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, Could not delete existing game directory" } }); M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogcouldNotFullyDeleteGameDirectory), M3L.GetString(M3L.string_errorRestoringGame), MessageBoxButton.OK, MessageBoxImage.Error); break; case RestoreResult.EXCEPTION_DELETING_GAME_DIRECTORY: Analytics.TrackEvent(@"Restored game", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Failure, Exception deleting existing game directory" } }); M3L.ShowDialog(window, M3L.GetString(M3L.string_dialogErrorOccuredDeletingGameDirectory), M3L.GetString(M3L.string_errorRestoringGame), MessageBoxButton.OK, MessageBoxImage.Error); break; case RestoreResult.RESTORE_OK: Analytics.TrackEvent(@"Restored game", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"Result", @"Success" } }); break; } } EndRestore(); CommandManager.InvalidateRequerySuggested(); }; var restoreTargetPath = RestoreTarget.TargetPath; if (RestoreTarget.IsCustomOption) { CommonOpenFileDialog m = new CommonOpenFileDialog { IsFolderPicker = true, EnsurePathExists = true, Title = M3L.GetString(M3L.string_selectNewRestoreDestination) }; if (m.ShowDialog() == CommonFileDialogResult.Ok) { //Check empty restoreTargetPath = m.FileName; if (Directory.Exists(restoreTargetPath)) { if (Directory.GetFiles(restoreTargetPath).Length > 0 || Directory.GetDirectories(restoreTargetPath).Length > 0) { Log.Warning($@"The selected restore directory is not empty: {restoreTargetPath}"); //Directory not empty if (!useNewMethod) { M3L.ShowDialog(window, M3L.GetString(M3L .string_dialogDirectoryIsNotEmptyLocationToRestoreToMustBeEmpty), M3L.GetString(M3L.string_cannotRestoreToThisLocation), MessageBoxButton.OK, MessageBoxImage.Error); return; } else { // Warn user var shouldContinue = MessageBoxResult.Yes == M3L.ShowDialog(window, M3L.GetString(M3L.string_interp_directoryNotEmptyWillDeleteEverything, restoreTargetPath), M3L.GetString(M3L.string_directoryNotEmpty), MessageBoxButton.YesNo, MessageBoxImage.Warning); if (!shouldContinue) { return; } Log.Warning($@"The user is continuing to new-gen restore on existing directory anyways"); } } //TODO: PREVENT RESTORING TO DOCUMENTS/BIOWARE } Analytics.TrackEvent(@"Chose to restore game to custom location", new Dictionary <string, string>() { { @"Game", Game.ToString() }, { @"New-gen", useNewMethod.ToString() } }); } else { return; } } RefreshTargets = true; TaskbarHelper.SetProgress(0); TaskbarHelper.SetProgressState(TaskbarProgressBarState.Normal); nbw.RunWorkerAsync(restoreTargetPath); } }