/// <summary>
		/// This initializes the services required to run the client.
		/// </summary>
		/// <param name="p_gmdGameMode">The game mode for which mods are being managed.</param>
		/// <param name="p_mrpModRepository">The mod repository to use to retrieve mods and mod metadata.</param>
		/// <param name="p_nfuFileUtility">The file utility class.</param>
		/// <param name="p_scxUIContext">The <see cref="SynchronizationContext"/> to use to marshall UI interactions to the UI thread.</param>
		/// <param name="p_vwmErrorMessage">The error message if the UAC check failed.</param>
		/// <returns>A <see cref="ServiceManager"/> containing the initialized services, or <c>null</c> if the
		/// services didn't initialize properly.</returns>
		protected ServiceManager InitializeServices(IGameMode p_gmdGameMode, IModRepository p_mrpModRepository, NexusFileUtil p_nfuFileUtility, SynchronizationContext p_scxUIContext, out ViewMessage p_vwmErrorMessage)
		{
			IModCacheManager mcmModCacheManager = new NexusModCacheManager(p_gmdGameMode.GameModeEnvironmentInfo.ModCacheDirectory, p_gmdGameMode.GameModeEnvironmentInfo.ModDirectory, p_nfuFileUtility);

			Trace.TraceInformation("Registering supported Script Types...");
			Trace.Indent();
			IScriptTypeRegistry stgScriptTypeRegistry = ScriptTypeRegistry.DiscoverScriptTypes(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "ScriptTypes"), p_gmdGameMode);
			if (stgScriptTypeRegistry.Types.Count == 0)
			{
				p_vwmErrorMessage = new ViewMessage("No script types were found.", null, "No Script Types", MessageBoxIcon.Error);
				return null;
			}
			Trace.TraceInformation("Found {0} script types.", stgScriptTypeRegistry.Types.Count);
			Trace.Unindent();

			Trace.TraceInformation("Registering supported mod formats...");
			Trace.Indent();
			IModFormatRegistry mfrModFormatRegistry = ModFormatRegistry.DiscoverFormats(mcmModCacheManager, stgScriptTypeRegistry, Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "ModFormats"));
			if (mfrModFormatRegistry.Formats.Count == 0)
			{
				p_vwmErrorMessage = new ViewMessage("No mod formats were found.", null, "No Mod Formats", MessageBoxIcon.Error);
				return null;
			}
			Trace.TraceInformation("Found {0} formats.", mfrModFormatRegistry.Formats.Count);
			Trace.Unindent();

			Trace.TraceInformation("Finding managed mods...");
			Trace.Indent();

			ModRegistry mrgModRegistry = null;
			try
			{
				mrgModRegistry = ModRegistry.DiscoverManagedMods(mfrModFormatRegistry, mcmModCacheManager, p_gmdGameMode.GameModeEnvironmentInfo.ModDirectory, EnvironmentInfo.Settings.ScanSubfoldersForMods, p_gmdGameMode, p_gmdGameMode.GameModeEnvironmentInfo.ModCacheDirectory, p_gmdGameMode.GameModeEnvironmentInfo.ModDownloadCacheDirectory, p_gmdGameMode.GameModeEnvironmentInfo.ModReadMeDirectory, p_gmdGameMode.GameModeEnvironmentInfo.CategoryDirectory);
			}
			catch (UnauthorizedAccessException ex)
			{
				p_vwmErrorMessage = new ViewMessage(String.Format("An error occured while retrieving managed mods: \n\n{0}", ex.Message), null, "Install Log", MessageBoxIcon.Error);
				return null;
			}

			Trace.TraceInformation("Found {0} managed mods.", mrgModRegistry.RegisteredMods.Count);
			Trace.Unindent();

			Trace.TraceInformation("Initializing Install Log...");
			Trace.Indent();
			Trace.TraceInformation("Checking if upgrade is required...");
			InstallLogUpgrader iluUgrader = new InstallLogUpgrader();

			string strLogPath = string.Empty;

			try
			{
				strLogPath = Path.Combine(p_gmdGameMode.GameModeEnvironmentInfo.InstallInfoDirectory, "InstallLog.xml");
			}
			catch (ArgumentNullException)
			{
				p_vwmErrorMessage = new ViewMessage("Unable to retrieve critical paths from the config file." + Environment.NewLine + "Select this game again to fix the folders setup.", null, "Config error", MessageBoxIcon.Warning);
				return null;
			}

			if (!InstallLog.IsLogValid(strLogPath))
				InstallLog.Restore(strLogPath);
			if (iluUgrader.NeedsUpgrade(strLogPath))
			{
				if (!iluUgrader.CanUpgrade(strLogPath))
				{
					p_vwmErrorMessage = new ViewMessage(String.Format("{0} does not support version {1} of the Install Log.", EnvironmentInfo.Settings.ModManagerName, InstallLog.ReadVersion(strLogPath)), null, "Install Log", MessageBoxIcon.Error);
					return null;
				}
				IBackgroundTask tskUpgrader = iluUgrader.UpgradeInstallLog(strLogPath, p_gmdGameMode.GameModeEnvironmentInfo.ModDirectory, mrgModRegistry);
				m_areTaskWait.Reset();
				tskUpgrader.TaskEnded += new EventHandler<TaskEndedEventArgs>(Task_TaskEnded);
				OnTaskStarted(tskUpgrader);
				if (tskUpgrader.IsActive)
					m_areTaskWait.WaitOne();
				tskUpgrader.TaskEnded -= new EventHandler<TaskEndedEventArgs>(Task_TaskEnded);
				if (tskUpgrader.Status != TaskStatus.Complete)
				{
					string strDetails = (string)(tskUpgrader.ReturnValue ?? null);
					p_vwmErrorMessage = new ViewMessage("Install Log was not upgraded.", strDetails, "Install Log", MessageBoxIcon.Error);
					return null;
				}
			}
			IInstallLog ilgInstallLog = InstallLog.Initialize(mrgModRegistry, p_gmdGameMode.GameModeEnvironmentInfo.ModDirectory, strLogPath);
			Trace.Unindent();

			Trace.TraceInformation("Initializing Plugin Management Services...");
			Trace.Indent();
			PluginRegistry prgPluginRegistry = null;
			IPluginOrderLog polPluginOrderLog = null;
			ActivePluginLog aplPluginLog = null;
			IPluginManager pmgPluginManager = null;
			if (!p_gmdGameMode.UsesPlugins)
				Trace.TraceInformation("Not required.");
			else
			{
				Trace.TraceInformation("Initializing Plugin Registry...");
				Trace.Indent();
				prgPluginRegistry = PluginRegistry.DiscoverManagedPlugins(p_gmdGameMode.GetPluginFactory(), p_gmdGameMode.GetPluginDiscoverer());
				Trace.TraceInformation("Found {0} managed plugins.", prgPluginRegistry.RegisteredPlugins.Count);
				Trace.Unindent();

				Trace.TraceInformation("Initializing Plugin Order Log...");
				Trace.Indent();
				polPluginOrderLog = PluginOrderLog.Initialize(prgPluginRegistry, p_gmdGameMode.GetPluginOrderLogSerializer(), p_gmdGameMode.GetPluginOrderValidator());
				Trace.Unindent();

				Trace.TraceInformation("Initializing Active Plugin Log...");
				Trace.Indent();
				aplPluginLog = ActivePluginLog.Initialize(prgPluginRegistry, p_gmdGameMode.GetActivePluginLogSerializer(polPluginOrderLog));
				Trace.Unindent();

				Trace.TraceInformation("Initializing Plugin Manager...");
				Trace.Indent();
				pmgPluginManager = PluginManager.Initialize(p_gmdGameMode, prgPluginRegistry, aplPluginLog, polPluginOrderLog, p_gmdGameMode.GetPluginOrderValidator());
				Trace.Unindent();
			}
			Trace.Unindent();

			Trace.TraceInformation("Initializing Activity Monitor...");
			Trace.Indent();
			DownloadMonitor dmtMonitor = new DownloadMonitor();
			Trace.Unindent();

            Trace.TraceInformation("Initializing Activate Mods Monitor...");
			Trace.Indent();
			ActivateModsMonitor ammMonitor = new ActivateModsMonitor();
			Trace.Unindent();

			Trace.TraceInformation("Initializing Mod Manager...");
			Trace.Indent();
            ModManager mmgModManager = ModManager.Initialize(p_gmdGameMode, EnvironmentInfo, p_mrpModRepository, dmtMonitor, ammMonitor, mfrModFormatRegistry, mrgModRegistry, p_nfuFileUtility, p_scxUIContext, ilgInstallLog, pmgPluginManager);
			Trace.Unindent();

			Trace.TraceInformation("Initializing Update Manager...");
			Trace.Indent();
			UpdateManager umgUpdateManager = new UpdateManager(p_gmdGameMode, EnvironmentInfo);
			Trace.Unindent();

			p_vwmErrorMessage = null;
            return new ServiceManager(ilgInstallLog, aplPluginLog, polPluginOrderLog, p_mrpModRepository, mmgModManager, pmgPluginManager, dmtMonitor, ammMonitor, umgUpdateManager);
		}
示例#2
0
        static int DoInstall(string game, string filename, string installationPath, string profilePath, string gamePath,
            List<string> additionalSearchPaths, string seVersion, ref string errorString)
        {
            if (game == null)
            {
                errorString = "no game specified";
                return 1;
            }
            if (filename == null)
            {
                errorString = "no file specified";
                return 1;
            }
            if (profilePath == null)
            {
                errorString = "no profile path specified";
                return 1;
            }
            if (gamePath == null)
            {
                errorString = "no game path specified";
                return 1;
            }
            try
            {
                EnvironmentInfo environmentInfo = new EnvironmentInfo(Properties.Settings.Default);

                string exeLocation = Assembly.GetExecutingAssembly().Location;
                string exePath = System.IO.Path.GetDirectoryName(exeLocation);
                string[] gameModes = Directory.GetFiles(Path.Combine(exePath, "GameModes"), String.Format("{0}.dll", game));
                if (gameModes.Count() == 0)
                {
                    errorString = "unknown game";
                    return 1;
                }

                Assembly gameAssembly = Assembly.LoadFrom(gameModes[0]);
                IGameModeFactory gameModeFactory = null;
                Type[] exportedTypes = gameAssembly.GetExportedTypes();
                foreach (Type type in exportedTypes)
                {
                    if (typeof(IGameModeFactory).IsAssignableFrom(type) && !type.IsAbstract)
                    {
                        ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(EnvironmentInfo) });
                        gameModeFactory = (IGameModeFactory)constructor.Invoke(new Object[] { environmentInfo });
                    }
                }
                if (gameModeFactory == null)
                {
                    errorString = "invalid game";
                    return 1;
                }

                string str7zPath = Path.Combine(environmentInfo.ProgrammeInfoDirectory, environmentInfo.Is64BitProcess ? "7z-64bit.dll" : "7z-32bit.dll");
                SevenZipCompressor.SetLibraryPath(str7zPath);

                FileUtil fileUtil = new NexusFileUtil(environmentInfo);

                environmentInfo.Settings.InstallationPaths[gameModeFactory.GameModeDescriptor.ModeId] = installationPath;
                environmentInfo.Settings.ModFolder[gameModeFactory.GameModeDescriptor.ModeId] = installationPath;
            //                environmentInfo.Settings.InstallInfoFolder[gameModeFactory.GameModeDescriptor.ModeId] = environmentInfo.TemporaryPath;
                environmentInfo.Settings.InstallInfoFolder[gameModeFactory.GameModeDescriptor.ModeId] = Path.Combine(installationPath, "temp");
                if (environmentInfo.Settings.DelayedSettings[gameModeFactory.GameModeDescriptor.ModeId] == null)
                    environmentInfo.Settings.DelayedSettings[gameModeFactory.GameModeDescriptor.ModeId] = new KeyedSettings<string>();
                if (environmentInfo.Settings.DelayedSettings["ALL"] == null)
                    environmentInfo.Settings.DelayedSettings["ALL"] = new KeyedSettings<string>();

                ViewMessage warning = null;

                IGameMode gameMode = gameModeFactory.BuildGameMode(fileUtil, out warning);

                IModCacheManager cacheManager = new NexusModCacheManager(environmentInfo.TemporaryPath, gameMode.GameModeEnvironmentInfo.ModDirectory, fileUtil);

                IScriptTypeRegistry scriptTypeRegistry = ScriptTypeRegistry.DiscoverScriptTypes(Path.Combine(Path.GetDirectoryName(exeLocation), "ScriptTypes"), gameMode, new List<string>());
                if (scriptTypeRegistry.Types.Count == 0)
                {
                    errorString = "No script types were found.";
                    return 2;
                }

                // use a proxy so we can intercept accesses to the IGameMode interface. This allows us to make the additional search paths accessible from
                // the sandbox and feed in the script extender version even though the nmm lib won't find it.
                // This has to happen after DiscoverScriptTypes becaus that function tries to localize the assembly which fails for the dynamic assembly
                // of the proxy. Fortunately DiscoverScriptTypes has no side-effects on the gameMode.
                // This recreates the gamemode object so it's important no code above modifies gameMode
                ProxyGenerator generator = new ProxyGenerator();
                GameModeInterceptor interceptor = new GameModeInterceptor(additionalSearchPaths, seVersion != null ? new Version(seVersion) : null);

                gameMode = (IGameMode)generator.CreateClassProxy(gameMode.GetType(), new object[] { environmentInfo, fileUtil }, new IInterceptor[] { interceptor });

                IModFormatRegistry formatRegistry = ModFormatRegistry.DiscoverFormats(cacheManager, gameMode.SupportedFormats, scriptTypeRegistry, Path.Combine(Path.GetDirectoryName(exeLocation), "ModFormats"));
                if (formatRegistry.Formats.Count == 0)
                {
                    errorString = "No formats were found.";
                    return 2;
                }

                // we install the mod from the temporary path. Unfortunately this requires the archive to be copied, otherwise the sandbox will
                // prevent the installer script from accessing the archive in its original location
                string fileNameTemporary = Path.Combine(environmentInfo.TemporaryPath, Path.GetFileName(filename));
                File.Copy(filename, fileNameTemporary);
                IMod mod = CreateMod(fileNameTemporary, formatRegistry, gameMode);
                if (mod == null)
                {
                    errorString = "failed to initialize mod";
                    return 3;
                }

                System.IO.File.WriteAllText(installationPath + "/__installInfo.txt", mod.ModName + "\n" + mod.HumanReadableVersion + "\n" + mod.Id);

                if (mod.HasInstallScript)
                {
                    DummyDataFileUtilFactory dummyFactory = null;
                    IDataFileUtil dataFileUtility;
                    Logger.Info("Detected C# script that relies on files in the actual data folder");

                    string modlistFile = Path.Combine(profilePath, "modlist.txt");
                    // ASSUMED mods path is the parent directory of the gameMode.InstallationPath
                    string modsPath = Directory.GetParent(gameMode.InstallationPath).FullName;
                    // Prepare dummy data directory
                    dummyFactory = new DummyDataFileUtilFactory(gameMode.GameModeEnvironmentInfo.InstallationPath, modlistFile, modsPath, gamePath, additionalSearchPaths);
                    dataFileUtility = dummyFactory.CreateDummyDataFileUtil();

                    TxFileManager fileManager = new TxFileManager();
                    IInstallLog installLog = new DummyInstallLog();
                    IIniInstaller iniIniInstaller = new IniInstaller(mod, installLog, fileManager, delegate { return OverwriteResult.No; });
                    IPluginManager pluginManager = new DummyPluginManager(Path.Combine(profilePath, "plugins.txt"), gameMode, mod);
                    IGameSpecificValueInstaller gameSpecificValueInstaller = gameMode.GetGameSpecificValueInstaller(mod, installLog, fileManager, new NexusFileUtil(environmentInfo), delegate { return OverwriteResult.No; });
                    IModFileInstaller fileInstaller = new ModFileInstaller(gameMode.GameModeEnvironmentInfo, mod, installLog, pluginManager, dataFileUtility, fileManager, delegate { return OverwriteResult.No; }, false);
                    InstallerGroup installers = new InstallerGroup(dataFileUtility, fileInstaller, iniIniInstaller, gameSpecificValueInstaller, pluginManager);
                    IVirtualModActivator modActivator = new DummyVirtualModActivator(gameMode, environmentInfo);
                    IScriptExecutor executor = mod.InstallScript.Type.CreateExecutor(mod, gameMode, environmentInfo, modActivator, installers, SynchronizationContext.Current);
                    // read-only transactions are waaaay faster, especially for solid archives) because the extractor isn't recreated for every extraction (why exactly would it be otherwise?)
                    mod.BeginReadOnlyTransaction(fileUtil);
                    // run the script in a second thread and start the main loop in the main thread to ensure we can handle message boxes and the like
                    ScriptRunner runner = new ScriptRunner(executor, mod.InstallScript);

                    runner.Execute();
                    runner.TaskEnded += delegate
                    {
                        iniIniInstaller.FinalizeInstall();
                        gameSpecificValueInstaller.FinalizeInstall();
                        mod.EndReadOnlyTransaction();

                        Application.Exit();
                    };

                    Application.Run();
                    switch (runner.Status)
                    {
                        case BackgroundTasks.TaskStatus.Cancelled: return 11;
                        case BackgroundTasks.TaskStatus.Error: return 6;
                        case BackgroundTasks.TaskStatus.Incomplete: return 10;
                        default: return 0;
                    }
                }
                else
                {
                    errorString = "no install script";
                    return 4;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("exception: " + e.Message);
                MessageBox.Show(e.Message, "Installation failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return 5;
            }
        }