private static bool Solve2009Version(LoaderOptions options, ref CryptoInfo cryptoInfo) { Log.Trace("Trying to solve outdated version."); var destDirName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Character Builder"); if (Directory.Exists(destDirName)) { options.CBPath = destDirName; cryptoInfo = new CryptoInfo(options); Log.Trace($"Using pre-patched {destDirName}"); return(true); } var defaultPath = @"C:\Program Files\Wizards of the Coast\Character Builder".Replace('\\', Path.DirectorySeparatorChar); Log.Trace($" - Looking in {defaultPath}"); if (Directory.Exists(defaultPath)) { Log.Trace($" - Applying patch"); var path = Patch(options.CBPath, defaultPath); if (!string.IsNullOrEmpty(path)) { Log.Trace($" - Patch works. Moving to {destDirName}"); Utils.CopyAll(path, destDirName); new DirectoryInfo(path).Delete(true); options.CBPath = destDirName; cryptoInfo = new CryptoInfo(options); Log.Trace($"Patch successful"); var baseconfigpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "default.cbconfig"); if (File.Exists(baseconfigpath)) // Point the config file at this for future launches { var doc = System.Xml.Linq.XDocument.Load(baseconfigpath); doc.Root.Add(new System.Xml.Linq.XElement("CharacterBuilderPath", options.CBPath)); doc.Save(baseconfigpath); } Log.Warn("CBLoader has manually reapplied a failed April2010 patch install."); return(true); } } return(false); }
public static Thread StartProcess(LoaderOptions options, string[] args, string redirectPath, string changelog) { Log.Info("Preparing to start CharacterBuilder.exe"); var stopwatch = new Stopwatch(); stopwatch.Start(); redirectPath = Path.GetFullPath(redirectPath); Log.Debug(" - Creating application domain."); var setup = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory, ApplicationName = "D&D 4E Character Builder", DisallowCodeDownload = true, DisallowPublisherPolicy = true }; // For some reason, unless we set PrivateBinPathProbe, D20RulesEngine.dll bypasses ResolveAssembly setup.PrivateBinPath = setup.ApplicationBase; setup.PrivateBinPathProbe = "true"; var appDomain = AppDomain.CreateDomain("D&D 4E Character Builder", null, setup, FULL_TRUST); Log.Debug(" - Creating remote callback."); var callbackObj = appDomain.CreateInstance("CBLoader", typeof(TargetDomainCallback).FullName); var callback = (TargetDomainCallback)callbackObj.Unwrap(); // Seal the AppDomain by setting the private path to an invalid path. // For some reason, we must *also* do this to stop D20RulesEngine.dll from bypassing. #pragma warning disable CS0618 appDomain.ClearPrivatePath(); appDomain.AppendPrivatePath("<|>"); #pragma warning restore CS0618 callback.Init(options.CBPath, Log.RemoteReceiver, Path.GetFullPath(redirectPath), Path.GetFullPath(changelog)); Log.Debug(" - Patching CharacterBuilder.exe"); PatchApplication(callback, options.CBPath, changelog); Log.Debug(" - Patching ApplicationUpdate.Client.dll"); PatchApplicationUpdate(callback, options.CBPath); Log.Debug(" - Setting up environment."); Environment.CurrentDirectory = options.CBPath; stopwatch.Stop(); Log.Debug($"Finished in {stopwatch.ElapsedMilliseconds} ms"); Log.Debug(); Log.Info("Launching CharacterBuilder.exe"); var thread = new Thread(() => { var hideLog = !Log.VerboseMode; if (hideLog) { ConsoleWindow.SetConsoleShown(false); } appDomain.ExecuteAssemblyByName("CharacterBuilder", null, args); Log.Debug("CharacterBuilder.exe terminated."); if (hideLog && Log.ErrorLogged) { ConsoleWindow.SetConsoleShown(true); } }); thread.SetApartmentState(ApartmentState.STA); thread.Start(); return(thread); }
private static LoaderOptions ProcessOptions(string[] args) { var options = new LoaderOptions(); var showHelp = false; var noConfig = false; string configFile = null; string keyFile = null; string cbPath = null; string cachePath = null; bool?writeKeyFile = null; bool?verboseMode = null; bool?forceUpdate = null; bool?forceRemerge = null; bool?launchBuilder = null; bool?checkForUpdates = null; bool?updateFirst = null; bool?setFileAssociations = null; bool?dumpTemporaryFiles = null; bool?createUpdateIndexFiles = null; var opts = new OptionSet() { "Usage: CBLoader [-c <config file>]", "A homebrew rules loader for the D&D Insider Character Builder", "", { "h|?|help", "Shows this help message.", value => showHelp = true }, { "v|verbose", "Enables additional debugging output.", value => verboseMode = true }, { "c|config=", "A config file to use rather than the default.", value => SetUniqueString(ref configFile, "-c", value) }, { "no-config", "Do not use a configuration file.", value => noConfig = true }, { "a|set-assocations", "Associate .dnd4e and .cbconfig with CBLoader.", value => setFileAssociations = false }, "", "Path management:", { "u|cache-path=", "Sets where to write temporary files.", value => SetUniqueString(ref cachePath, "-u", value) }, { "cb-path=", "Sets where character builder is installed.", value => SetUniqueString(ref cbPath, "--cb-path", value) }, { "f|folder=", "Adds a directory to search for custom rules in.", value => options.AddPath(value) }, { "ignore-part=", "Adds a part file to ignore.", value => options.IgnoreParts.Add(value) }, "", "Keyfile options:", { "k|key-file=", "Uses the given keyfile.", value => SetUniqueString(ref keyFile, "-k", value) }, { "r=", "Updates a keyfile at the given path. Implies -k.", value => { SetUniqueString(ref keyFile, "-r", value); writeKeyFile = true; } }, "", "Execution options:", { "update-first", "Update before merging, rather than after.", value => updateFirst = true }, { "force-update", "Redownload parts files.", value => forceUpdate = true }, { "e|force-remerge", "Always regenerate merged rules file.", value => forceRemerge = true }, { "d|no-update", "Do not check for updates.", value => checkForUpdates = false }, "", "Development options:", { "n|no-run", "Do not actually launch the character builder.", value => launchBuilder = false }, { "dump-temporary", "Dumps raw rules data to disk.", value => dumpTemporaryFiles = true }, { "create-update-indexes", "Create update version indexes.", value => createUpdateIndexFiles = true }, }; var execArgs = opts.Parse(args); if (showHelp) { opts.WriteOptionDescriptions(Console.Out); return(null); } // Load a configation file. if (!noConfig) { if (configFile == null) { options.AddOptionFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "default.cbconfig")); } else { options.AddOptionFile(configFile); } } // Copy configuration options from console. if (keyFile != null) { options.KeyFile = keyFile; } if (cbPath != null) { options.CBPath = cbPath; } if (cachePath != null) { options.CachePath = cachePath; } if (writeKeyFile != null) { options.WriteKeyFile = (bool)writeKeyFile; } if (verboseMode != null) { options.VerboseMode = (bool)verboseMode; } if (forceUpdate != null) { options.ForceUpdate = (bool)forceUpdate; } if (forceRemerge != null) { options.ForceRemerge = (bool)forceRemerge; } if (launchBuilder != null) { options.LaunchBuilder = (bool)launchBuilder; } if (checkForUpdates != null) { options.CheckForUpdates = (bool)checkForUpdates; } if (updateFirst != null) { options.UpdateFirst = (bool)updateFirst; } if (setFileAssociations != null) { options.SetFileAssociations = (bool)setFileAssociations; } if (dumpTemporaryFiles != null) { options.DumpTemporaryFiles = (bool)dumpTemporaryFiles; } if (createUpdateIndexFiles != null) { options.CreateUpdateIndexFiles = (bool)createUpdateIndexFiles; } if (options.CBPath == null && (options.CBPath = Utils.GetInstallPath()) == null) { throw new CBLoaderException( "CBLoader could not find an installation of Character Builder.\n" + "Please specify its path with <CBPath>path/to/builder</CBPath> in the configuration " + "or reinstall Character Builder."); } // Default cache Path if (options.CachePath == null) { options.CachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Cache"); } // Default keyfile location. if (options.KeyFile == null) { options.KeyFile = Path.Combine(options.CachePath, "cbloader.keyfile"); } // Default part directory. if (options.MergeDirectories.Count == 0 && options.UpdateDirectories.Count == 0) { options.AddPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Custom")); } options.AddPath(Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "ddi"), "CBLoader")); // Update first anyway if LaunchBuilder isn't set -- we don't need this optimization. if (!options.LaunchBuilder) { options.UpdateFirst = true; } // Check configuration option consistancy. options.FinalOptionsCheck(); return(options); }