Exemplo n.º 1
0
        private static void PerformRAMCheck(Action <string, string> messageCallback)
        {
            var ramAmountsBytes = Utilities.GetInstalledRamAmount();
            var installedRamGB  = ramAmountsBytes * 1.0d / (2 ^ 30);

            if (ramAmountsBytes > 0 && installedRamGB < 10)
            {
                messageCallback?.Invoke("System memory is less than 10 GB", "Randomization can use significant amounts of memory (up to 6GB) in multithreaded mode. It is recommended that you disable multithreaded randomization if your system has less than 10GB of memory. This will increase randomization time but will reduce the memory required to randomize.");
            }
#if WINDOWS
            //Check pagefile
            try
            {
                //Current
                var pageFileLocations = new List <string>();
                using (var query = new ManagementObjectSearcher("SELECT Caption,AllocatedBaseSize FROM Win32_PageFileUsage"))
                {
                    foreach (ManagementBaseObject obj in query.Get())
                    {
                        string pagefileName = (string)obj.GetPropertyValue("Caption");
                        MERLog.Information("Detected pagefile: " + pagefileName);
                        pageFileLocations.Add(pagefileName.ToLower());
                    }
                }

                //Max
                using (var query = new ManagementObjectSearcher("SELECT Name,MaximumSize FROM Win32_PageFileSetting"))
                {
                    foreach (ManagementBaseObject obj in query.Get())
                    {
                        string pagefileName = (string)obj.GetPropertyValue("Name");
                        uint   max          = (uint)obj.GetPropertyValue("MaximumSize");
                        if (max > 0)
                        {
                            // Not system managed
                            pageFileLocations.RemoveAll(x => Path.GetFullPath(x).Equals(Path.GetFullPath(pagefileName)));
                            MERLog.Error($"Pagefile has been modified by the end user. The maximum page file size on {pagefileName} is {max} MB. Does this user **actually** know what capping a pagefile does?");
                        }
                    }
                }

                if (pageFileLocations.Any())
                {
                    MERLog.Information("We have a usable system managed page file - OK");
                }
                else
                {
                    MERLog.Error("We have no uncapped or available pagefiles to use! Very high chance application will run out of memory");
                    messageCallback?.Invoke($"Pagefile is off or size has been capped", $"The system pagefile (virtual memory) settings are not currently managed by Windows, or the pagefile is off. Mass Effect 2 Randomizer uses significant amounts of memory and will crash if the system runs low on memory. You should always leave page files managed by Windows.");
                }
            }
            catch (Exception e)
            {
                MERLog.Exception(e, "Unable to check pagefile settings:");
            }
#endif
        }
        /// <summary>
        /// Allows loading a list of names for pawns
        /// </summary>
        public static void SetupRandomizer(RandomizationOption option)
        {
            OpenFileDialog ofd = new OpenFileDialog()
            {
                Title  = "Select text file with list of names, one per line",
                Filter = "Text files|*.txt",
            };
            var result = ofd.ShowDialog();

            if (result.HasValue && result.Value)
            {
                try
                {
                    PawnNames.ReplaceAll(File.ReadAllLines(ofd.FileName));
                    option.Description = $"{PawnNames.Count} name(s) loaded for randomization";
                }
                catch (Exception e)
                {
                    MERLog.Exception(e, "Error reading names for CharacterNames randomizer");
                }
            }
        }
Exemplo n.º 3
0
        public static async void BeginFlow(MainWindow window)
        {
            // PRE LIBRARY LOAD
            RegistryHandler.RegistrySettingsPath       = @"HKEY_CURRENT_USER\Software\MassEffect2Randomizer";
            RegistryHandler.CurrentUserRegistrySubpath = @"Software\MassEffect2Randomizer";
            LegendaryExplorerCoreLib.SetSynchronizationContext(TaskScheduler.FromCurrentSynchronizationContext());

            try
            {
                // This is in a try catch because this is a critical no-crash zone that is before launch
                window.Title = $"Mass Effect 2 Randomizer {App.AppVersion}";
            }
            catch { }

            if (Utilities.GetExecutablePath().StartsWith(Path.GetTempPath(), StringComparison.InvariantCultureIgnoreCase))
            {
                // Running from temp! This is not allowed
                await window.ShowMessageAsync("Cannot run from temp directory", $"Mass Effect 2 Randomizer cannot be run from the system's Temp directory. If this executable was run from within an archive, it needs to be extracted first.");

                Environment.Exit(1);
            }

            var pd = await window.ShowProgressAsync("Starting up", $"Mass Effect 2 Randomizer is starting up. Please wait.");

            pd.SetIndeterminate();
            NamedBackgroundWorker bw = new NamedBackgroundWorker("StartupThread");

            bw.DoWork += (a, b) =>
            {
                ALOTInstallerCoreLib.Startup(SetWrapperLogger, RunOnUIThread, startTelemetry, stopTelemetry, $"Mass Effect 2 Randomizer {App.AppVersion} starting up", false);
                // Logger is now available

                // Setup telemetry handlers
                CoreAnalytics.TrackEvent = TelemetryController.TrackEvent;
                CoreCrashes.TrackError   = TelemetryController.TrackError;
                CoreCrashes.TrackError2  = TelemetryController.TrackError2;
                CoreCrashes.TrackError3  = TelemetryController.TrackError3;

                // Setup the InteropPackage for the update check
                #region Update interop
                CancellationTokenSource ct = new CancellationTokenSource();

                AppUpdateInteropPackage interopPackage = new AppUpdateInteropPackage()
                {
                    GithubOwner              = "Mgamerz",
                    GithubReponame           = "MassEffect2Randomizer",
                    UpdateAssetPrefix        = "ME2Randomizer",
                    UpdateFilenameInArchive  = "ME2Randomizer.exe",
                    ShowUpdatePromptCallback = (title, text, updateButtonText, declineButtonText) =>
                    {
                        bool   response = false;
                        object syncObj  = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                var result = await mw.ShowMessageAsync(title, text, MessageDialogStyle.AffirmativeAndNegative, new MetroDialogSettings()
                                {
                                    AffirmativeButtonText = updateButtonText,
                                    NegativeButtonText    = declineButtonText,
                                    DefaultButtonFocus    = MessageDialogResult.Affirmative
                                },
                                                                       75);
                                response = result == MessageDialogResult.Affirmative;
                                lock (syncObj)
                                {
                                    Monitor.Pulse(syncObj);
                                }
                            }
                        });
                        lock (syncObj)
                        {
                            Monitor.Wait(syncObj);
                        }
                        return(response);
                    },
                    ShowUpdateProgressDialogCallback = (title, initialmessage, canCancel) =>
                    {
                        // We don't use this as we are already in a progress dialog
                        pd.SetCancelable(canCancel);
                        pd.SetMessage(initialmessage);
                        pd.SetTitle(title);
                    },
                    SetUpdateDialogTextCallback = s =>
                    {
                        pd.SetMessage(s);
                    },
                    ProgressCallback = (done, total) =>
                    {
                        pd.SetProgress(done * 1d / total);
                        pd.SetMessage($"Downloading update {FileSize.FormatSize(done)} / {FileSize.FormatSize(total)}");
                    },
                    ProgressIndeterminateCallback = () =>
                    {
                        pd.SetIndeterminate();
                    },
                    ShowMessageCallback = (title, message) =>
                    {
                        object syncObj = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                await mw.ShowMessageAsync(title, message);
                                lock (syncObj)
                                {
                                    Monitor.Pulse(syncObj);
                                }
                            }
                        });
                        lock (syncObj)
                        {
                            Monitor.Wait(syncObj);
                        }
                    },
                    NotifyBetaAvailable = () =>
                    {
                        App.BetaAvailable = true;
                    },
                    DownloadCompleted = () =>
                    {
                        pd.SetCancelable(false);
                    },
                    cancellationTokenSource    = ct,
                    ApplicationName            = "Mass Effect 2 Randomizer",
                    RequestHeader              = "ME2Randomizer",
                    ForcedUpgradeMaxReleaseAge = 3
                };

                #endregion



                pd.SetMessage("Checking for application updates");
                pd.Canceled += (sender, args) =>
                {
                    ct.Cancel();
                };
                AppUpdater.PerformGithubAppUpdateCheck(interopPackage);

                // If user aborts download
                pd.SetCancelable(false);
                pd.SetIndeterminate();
                pd.SetTitle("Starting up");

                void setStatus(string message)
                {
                    pd.SetIndeterminate();
                    pd.SetMessage(message);
                }

                GameTarget target = null;
                try
                {
                    pd.SetMessage("Loading Mass Effect 2 Randomizer framework");
                    ToolTipService.ShowOnDisabledProperty.OverrideMetadata(typeof(Control), new FrameworkPropertyMetadata(true));
                    ToolTipService.ShowDurationProperty.OverrideMetadata(typeof(DependencyObject), new FrameworkPropertyMetadata(int.MaxValue));

                    ALOTInstallerCoreLib.PostCriticalStartup(x => pd.SetMessage(x), RunOnUIThread, false);

#if __LE2__
                    LE2Directory.ReloadDefaultGamePath(true);
                    if (LE2Directory.DefaultGamePath != null)
                    {
                        GameTarget gt = new GameTarget(MEGame.LE2, LE2Directory.DefaultGamePath, true);
                        if (gt.ValidateTarget() == null)
                        {
                            Locations.SetTarget(gt, false);
                        }
                    }
#endif
                    MEPackageHandler.GlobalSharedCacheEnabled = false; // ME2R does not use the global shared cache.

                    handleM3Passthrough();
                    target = Locations.GetTarget(MERFileSystem.Game);
                    if (target == null)
                    {
                        var gamePath = MEDirectories.GetDefaultGamePath(MERFileSystem.Game);
                        if (Directory.Exists(gamePath))
                        {
                            target = new GameTarget(MERFileSystem.Game, gamePath, true);
                            var validationFailedReason = target.ValidateTarget();
                            if (validationFailedReason == null)
                            {
                                // CHECK NOT TEXTURE MODIFIED
                                if (target.TextureModded)
                                {
                                    MERLog.Error($@"Game target is texture modded: {target.TargetPath}. This game target is not targetable by ME2R");
                                    object o = new object();
                                    Application.Current.Dispatcher.Invoke(async() =>
                                    {
                                        if (Application.Current.MainWindow is MainWindow mw)
                                        {
                                            await mw.ShowMessageAsync("Mass Effect 2 target is texture modded", $"The game located at {target.TargetPath} has had textures modified. Mass Effect 2 Randomizer cannot randomize texture modified games, as it adds package files. If you want to texture mod your game, it must be done after randomization.", ContentWidthPercent: 75);
                                            lock (o)
                                            {
                                                Monitor.Pulse(o);
                                            }
                                        }
                                    });
                                    lock (o)
                                    {
                                        Monitor.Wait(o);
                                    }
                                }

                                // We still set target so we can restore game if necessary
                                Locations.SetTarget(target, false);
                            }
                        }
                    }


                    pd.SetMessage("Performing startup checks");
                    MERStartupCheck.PerformStartupCheck((title, message) =>
                    {
                        object o = new object();
                        Application.Current.Dispatcher.Invoke(async() =>
                        {
                            if (Application.Current.MainWindow is MainWindow mw)
                            {
                                await mw.ShowMessageAsync(title, message, ContentWidthPercent: 75);
                                lock (o)
                                {
                                    Monitor.Pulse(o);
                                }
                            }
                        });
                        lock (o)
                        {
                            Monitor.Wait(o);
                        }
                    }, x => pd.SetMessage(x));

                    // force initial refresh
                    MERPeriodicRefresh(null, null);
                }
                catch (Exception e)
                {
                    MERLog.Exception(e, @"There was an error starting up the framework!");
                }

                pd.SetMessage("Preparing interface");
                Thread.Sleep(250); // This will allow this message to show up for moment so user can see it.

                Application.Current.Dispatcher.Invoke(async() =>
                {
                    if (Application.Current.MainWindow is MainWindow mw)
                    {
                        mw.SetupTargetDescriptionText();


                        var backupStatus                = BackupService.GetBackupStatus(MERFileSystem.Game);
                        mw.BackupRestoreText            = backupStatus?.BackupActionText;
                        mw.BackupRestore_Button.ToolTip = backupStatus != null && backupStatus.BackedUp ? "Click to restore game/uninstall randomizer mod" : "Click to backup game";

                        mw.FinalizeInterfaceLoad();

                        /*
                         * if (!hasWorkingMEM)
                         * {
                         *  await mw.ShowMessageAsync("Required components are not available",
                         *      "Some components for installation are not available, likely due to network issues (blocking, no internet, etc). To install these components, folow the 'How to install the Installer Support Package' directions on any of the ALOT pages on NexusMods. The installer will not work without these files installed.",
                         *      ContentWidthPercent: 75);
                         * }*/

                        PeriodicRefresh.OnPeriodicRefresh += MERPeriodicRefresh;
                    }
                });
            };
            bw.RunWorkerCompleted += async(a, b) =>
            {
                // Post critical startup
                Random random  = new Random();
                var    preseed = random.Next();
                window.ImageCredits.ReplaceAll(ImageCredit.LoadImageCredits("imagecredits.txt", false));
                window.ContributorCredits.ReplaceAll(window.GetContributorCredits());
                window.LibraryCredits.ReplaceAll(LibraryCredit.LoadLibraryCredits("librarycredits.txt"));
#if DEBUG
                window.SeedTextBox.Text = 529572808.ToString();
#else
                window.SeedTextBox.Text = preseed.ToString();
#endif
                window.TextBlock_AssemblyVersion.Text = $"Version {App.AppVersion}";
                window.SelectedRandomizeMode          = MainWindow.RandomizationMode.ERandomizationMode_SelectAny;


                var hasFirstRun = RegistryHandler.GetRegistrySettingBool(MainWindow.SETTING_FIRSTRUN);
                if (hasFirstRun == null || !hasFirstRun.Value)
                {
                    window.FirstRunFlyoutOpen = true;
                }
                await pd.CloseAsync();
            };
            bw.RunWorkerAsync();
        }
Exemplo n.º 4
0
        private static bool PerformWriteCheck(Action <string, string> messageCallback)
        {
#if WINDOWS
            MERLog.Information("Performing write check on all game directories...");
            var targets = Locations.GetAllAvailableTargets();
            try
            {
                List <string> directoriesToGrant = new List <string>();
                foreach (var t in targets)
                {
                    // Check all folders are writable
                    bool isFullyWritable = true;
                    var  testDirectories = Directory.GetDirectories(t.TargetPath, "*", SearchOption.AllDirectories);
                    foreach (var d in testDirectories)
                    {
                        isFullyWritable &= Utilities.IsDirectoryWritable(d);
                    }
                }

                bool isAdmin = Utilities.IsAdministrator();

                if (directoriesToGrant.Any())
                {
                    string args = "";
                    // Some directories not writable
                    foreach (var dir in directoriesToGrant)
                    {
                        if (args != "")
                        {
                            args += " ";
                        }

                        args += $"\"{dir}\"";
                    }

                    args = $"\"{System.Security.Principal.WindowsIdentity.GetCurrent().Name}\" {args}";

                    throw new Exception("not implemented.");

                    /*
                     * var permissionsGranterExe = Path.Combine(Locations.ResourcesDir, "Binaries", "PermissionsGranter.exe");
                     *
                     * //need to run write permissions program
                     * if (isAdmin)
                     * {
                     *  int result = Utilities.RunProcess(permissionsGranterExe, args, true, true, true, true);
                     *  if (result == 0)
                     *  {
                     *      MERLog.Information("Elevated process returned code 0, directories are hopefully writable now.");
                     *      return true;
                     *  }
                     *  else
                     *  {
                     *      MERLog.Error("Elevated process returned code " + result +
                     *                ", directories probably aren't writable.");
                     *      return false;
                     *  }
                     * }
                     * else
                     * {
                     *  string message = $"The Mass Effect 2 game folder is not writeable by your user account. Mass Effect 2 Randomizer will attempt to grant access to these folders/registry with the PermissionsGranter.exe program:\n";
                     *
                     *  foreach (string str in directoriesToGrant)
                     *  {
                     *      message += "\n" + str;
                     *  }
                     *
                     *  messageCallback?.Invoke("Write permissions required for modding", message);
                     *  int result = Utilities.RunProcess(permissionsGranterExe, args, true, true, true, true);
                     *  if (result == 0)
                     *  {
                     *      MERLog.Information("Elevated process returned code 0, directories are hopefully writable now.");
                     *      return true;
                     *  }
                     *  else
                     *  {
                     *      MERLog.Error($"Elevated process returned code {result}, directories probably aren't writable.");
                     *      return false;
                     *  }
                     * }
                     */
                }
            }
            catch (Exception e)
            {
                MERLog.Exception(e, "Error checking for write privileges. This may be a significant sign that an installed game is not in a good state.");
                return(false);
            }
#endif
            return(true);
        }