Exemple #1
0
        public static void ApplyInstructions(LaunchType launchType, List <PatchGroup> patchGroups, ProgressObject totalProgress)
        {
            //TODO: Use a different progress tracking system and make the entire patching operation more recoverable and fault-tolerant.
            //TODO: Refactor this method.
            AppInfo appInfo = AppContextManager.Context.Value;

            Assembly myAttributesAssembly     = typeof(AppInfo).Assembly;
            string   myAttributesAssemblyName = Path.GetFileName(myAttributesAssembly.Location);

            var fileProgress  = new ProgressObject();
            var patchProgress = new ProgressObject();

            totalProgress.Child.Value = fileProgress;
            fileProgress.Child.Value  = patchProgress;

            totalProgress.SetTaskData("Patching Game", appInfo.AppName, patchGroups.Count);

            foreach (PatchGroup patchGroup in patchGroups)
            {
                int patchCount = patchGroup.Instructions.Count;

                string destinationPath = patchGroup.TargetPath;

                var patcher = new AssemblyPatcher(destinationPath, Logger);
                patcher.EmbedHistory = true;

                string sourcePath = PatchingHelper.GetBackupForModified(destinationPath);
                string backupPath = PatchingHelper.GetBackupForOriginal(destinationPath);

                // note that Path.Combine(FILENAME, "..", OTHER_FILENAME) doesn't work on Mono but does work on .NET.
                string targetDirectory = Path.GetDirectoryName(destinationPath);

                string localAssemblyName = Path.Combine(targetDirectory, myAttributesAssemblyName);

                totalProgress.SetTaskData(string.Format("Patching {0}", appInfo.AppName), Path.GetFileName(destinationPath));

                fileProgress.SetTaskData("Patching File", total: 2 + patchCount, increment: true);
                fileProgress.SetTaskData(taskText: "Applying Patch");

                if (!PatchingHelper.DoesFileMatchPatchList(sourcePath, destinationPath, patchGroup.Instructions) || PreferencesManager.Preferences.AlwaysPatch)
                {
                    try
                    {
                        myAttributesAssembly.TryCopyAttributesAssembly(localAssemblyName);
                    }
                    catch (Exception exception)
                    {
                        Logger.Warning(exception, "Failed to read local attributes assembly so it will be overwritten.");
                    }

                    foreach (PatchInstruction patch in patchGroup.Instructions)
                    {
                        try
                        {
                            patcher.TryPatchManifest(patch, patchGroup, patchProgress);
                        }
                        catch (PatchingProcessException exception)
                        {
                            Logger.Show(exception);
                        }

                        fileProgress.SetTaskData(increment: true);
                    }

                    patchProgress.SetTaskData(string.Empty, string.Empty);

                    fileProgress.SetTaskData(taskText: "Writing Assembly", increment: true);

                    if (launchType == LaunchType.Test && Environment.OSVersion.Platform == PlatformID.Win32NT)
                    {
                        fileProgress.SetTaskData(taskText: "Running PEVerify");

                        string peOutput = patcher.TryRunPeVerify(appInfo, destinationPath);

                        Logger.Information(peOutput);
                    }

                    try
                    {
                        patcher.TryBackup(sourcePath, patchGroup);
                    }
                    catch (PatchingProcessException exception)
                    {
                        Logger.Show(exception);
                    }
                }
                else
                {
                    fileProgress.Current.Value += patchCount;
                }

                try
                {
                    LaunchManager.TrySwitchFilesSafely(sourcePath, destinationPath, backupPath, patchGroup);
                }
                catch (PatchingProcessException exception)
                {
                    Logger.Show(exception);
                }

                AssemblyCache.Default.ClearCache();

                totalProgress.SetTaskData(increment: true);
            }
        }