/// <summary> /// Starts up the IPC listner channel to wait for message from other instances. /// </summary> /// <param name="p_eifEnvironmentInfo">The application's envrionment info.</param> /// <param name="p_gmdGameModeInfo">The descriptor of the game mode for which mods are being managed.</param> /// <param name="p_mmgModManager">The mod manager to use to manage mods.</param> /// <param name="p_frmMainForm">The main application form.</param> public static IMessager InitializeListener(EnvironmentInfo p_eifEnvironmentInfo, IGameModeDescriptor p_gmdGameModeInfo, ModManager p_mmgModManager, MainForm p_frmMainForm) { if (m_schMessagerChannel != null) throw new InvalidOperationException("The IPC Channel has already been created as a SERVER."); string strUri = String.Format("{0}-{1}IpcServer", p_eifEnvironmentInfo.Settings.ModManagerName, p_gmdGameModeInfo.ModeId); m_schMessagerChannel = new IpcServerChannel(strUri); ChannelServices.RegisterChannel(m_schMessagerChannel, true); MessagerServer msgMessager = new MessagerServer(p_mmgModManager, p_frmMainForm); string strEndpoint = String.Format("{0}Listener", p_gmdGameModeInfo.ModeId); RemotingServices.Marshal(msgMessager, strEndpoint, typeof(IMessager)); strUri += "/" + strEndpoint; string strTraceInfo = String.Format("Setting up listener on {0} at {1}", strUri, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); Trace.TraceInformation(strTraceInfo); return msgMessager; }
/// <summary> /// A simple constructor the initializes the object with the required dependencies. /// </summary> /// <param name="p_mmgModManager">The mod manager to use to manage mods.</param> /// <param name="p_frmMainForm">The main form of the client for which we listening for messages.</param> private MessagerServer(ModManager p_mmgModManager, MainForm p_frmMainForm) { ModManager = p_mmgModManager; MainForm = p_frmMainForm; }
/// <summary> /// Runs the applications /// </summary> /// <remarks> /// This method makes sure the environment is sane. If so, it creates the required services /// and launches the main form. /// </remarks> /// <param name="p_strArgs">The command line arguments passed to the application.</param> /// <returns><c>true</c> if the application started as expected; /// <c>false</c> otherwise.</returns> public bool RunMainForm(string[] p_strArgs) { if (!SandboxCheck(m_eifEnvironmentInfo)) return false; SetCompressorPath(m_eifEnvironmentInfo); string strRequestedGameMode = null; string[] strArgs = p_strArgs; Uri uriModToAdd = null; if ((p_strArgs.Length > 0) && !p_strArgs[0].StartsWith("-")) { if (Uri.TryCreate(p_strArgs[0], UriKind.Absolute, out uriModToAdd) && uriModToAdd.Scheme.Equals("nxm", StringComparison.OrdinalIgnoreCase)) strRequestedGameMode = uriModToAdd.Host; } else for (Int32 i = 0; i < p_strArgs.Length; i++) { string strArg = p_strArgs[i]; if (strArg.StartsWith("-")) { switch (strArg) { case "-game": strRequestedGameMode = p_strArgs[i + 1]; Trace.Write("Game Specified On Command line: " + strRequestedGameMode + ") "); break; } } } bool booChangeDefaultGameMode = false; GameModeRegistry gmrSupportedGames = GetSupportedGameModes(); do { NexusFontSetResolver nfrResolver = SetUpFonts(); GameModeRegistry gmrInstalledGames = GetInstalledGameModes(gmrSupportedGames); if (gmrInstalledGames == null) { Trace.TraceInformation("No installed games."); MessageBox.Show(String.Format("No games were detected! {0} will now close.", m_eifEnvironmentInfo.Settings.ModManagerName), "No Games", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } GameModeSelector gmsSelector = new GameModeSelector(gmrSupportedGames, gmrInstalledGames, m_eifEnvironmentInfo); IGameModeFactory gmfGameModeFactory = gmsSelector.SelectGameMode(strRequestedGameMode, booChangeDefaultGameMode); if (gmsSelector.RescanRequested) { m_eifEnvironmentInfo.Settings.InstalledGamesDetected = false; m_eifEnvironmentInfo.Settings.Save(); booChangeDefaultGameMode = true; continue; } if (gmfGameModeFactory == null) return false; Trace.TraceInformation(String.Format("Game Mode Factory Selected: {0} ({1})", gmfGameModeFactory.GameModeDescriptor.Name, gmfGameModeFactory.GameModeDescriptor.ModeId)); Mutex mtxGameModeMutex = null; bool booOwnsMutex = false; try { for (Int32 intAttemptCount = 0; intAttemptCount < 3; intAttemptCount++) { Trace.TraceInformation("Creating Game Mode mutex (Attempt: {0})", intAttemptCount); mtxGameModeMutex = new Mutex(true, String.Format("{0}-{1}-GameModeMutex", m_eifEnvironmentInfo.Settings.ModManagerName, gmfGameModeFactory.GameModeDescriptor.ModeId), out booOwnsMutex); //If the mutex is owned, you are the first instance of the mod manager for game mode, so break out of loop. if (booOwnsMutex) break; try { //If the mutex isn't owned, attempt to talk across the messager. using (IMessager msgMessager = MessagerClient.GetMessager(m_eifEnvironmentInfo, gmfGameModeFactory.GameModeDescriptor)) { if (msgMessager != null) { //Messenger was created OK, send download request, or bring to front. if (uriModToAdd != null) { Trace.TraceInformation(String.Format("Messaging to add: {0}", uriModToAdd)); msgMessager.AddMod(uriModToAdd.ToString()); } else { Trace.TraceInformation(String.Format("Messaging to bring to front.")); msgMessager.BringToFront(); } return true; } } mtxGameModeMutex.Close(); mtxGameModeMutex = null; } catch (InvalidOperationException) { StringBuilder stbPromptMessage = new StringBuilder(); stbPromptMessage.AppendFormat("{0} was unable to start. It appears another instance of {0} is already running.", m_eifEnvironmentInfo.Settings.ModManagerName).AppendLine(); stbPromptMessage.AppendFormat("If you were trying to download multiple files, wait for {0} to start before clicking on a new file download.", m_eifEnvironmentInfo.Settings.ModManagerName).AppendLine(); MessageBox.Show(stbPromptMessage.ToString(), "Already running", MessageBoxButtons.OK, MessageBoxIcon.Information); return false; } //Messenger couldn't be created, so sleep for a few seconds to give time for opening // the running copy of the mod manager to start up/shut down Thread.Sleep(TimeSpan.FromSeconds(5.0d)); } if (!booOwnsMutex) { HeaderlessTextWriterTraceListener htlListener = (HeaderlessTextWriterTraceListener)Trace.Listeners["DefaultListener"]; htlListener.ChangeFilePath(Path.Combine(Path.GetDirectoryName(htlListener.FilePath), "Messager" + Path.GetFileName(htlListener.FilePath))); Trace.TraceInformation("THIS IS A MESSAGER TRACE LOG."); if (!htlListener.TraceIsForced) htlListener.SaveToFile(); StringBuilder stbPromptMessage = new StringBuilder(); stbPromptMessage.AppendFormat("{0} was unable to start. It appears another instance of {0} is already running.", m_eifEnvironmentInfo.Settings.ModManagerName).AppendLine(); stbPromptMessage.AppendLine("A Trace Log file was created at:"); stbPromptMessage.AppendLine(htlListener.FilePath); stbPromptMessage.AppendLine("Before reporting the issue, don't close this window and check for a fix here (you can close it afterwards):"); stbPromptMessage.AppendLine("http://forums.nexusmods.com/index.php?/topic/721054-read-here-first-nexus-mod-manager-frequent-issues/"); stbPromptMessage.AppendLine("If you can't find a solution, please make a bug report and attach the TraceLog file here:"); stbPromptMessage.AppendLine("http://forums.nexusmods.com/index.php?/tracker/project-3-mod-manager-open-beta/"); MessageBox.Show(stbPromptMessage.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Information); return false; } //ApplicationInitializer ainInitializer = new ApplicationInitializer(m_eifEnvironmentInfo, nfrResolver); //ApplicationInitializationForm frmAppInitilizer = new ApplicationInitializationForm(ainInitializer); //ainInitializer.Initialize(gmfGameModeFactory, SynchronizationContext.Current); //frmAppInitilizer.ShowDialog(); ApplicationInitializer ainInitializer = null; ApplicationInitializationForm frmAppInitilizer = null; while ((ainInitializer == null) || (ainInitializer.Status == TaskStatus.Retrying)) { ainInitializer = new ApplicationInitializer(m_eifEnvironmentInfo, nfrResolver); frmAppInitilizer = new ApplicationInitializationForm(ainInitializer); ainInitializer.Initialize(gmfGameModeFactory, SynchronizationContext.Current); frmAppInitilizer.ShowDialog(); } if (ainInitializer.Status != TaskStatus.Complete) { if (ainInitializer.Status == TaskStatus.Error) return false; booChangeDefaultGameMode = true; DisposeServices(ainInitializer.Services); continue; } IGameMode gmdGameMode = ainInitializer.GameMode; ServiceManager svmServices = ainInitializer.Services; MainFormVM vmlMainForm = new MainFormVM(m_eifEnvironmentInfo, gmrInstalledGames, gmdGameMode, svmServices.ModRepository, svmServices.DownloadMonitor, svmServices.ActivateModsMonitor, svmServices.UpdateManager, svmServices.ModManager, svmServices.PluginManager); MainForm frmMain = new MainForm(vmlMainForm); using (IMessager msgMessager = MessagerServer.InitializeListener(m_eifEnvironmentInfo, gmdGameMode, svmServices.ModManager, frmMain)) { if (uriModToAdd != null) { Trace.TraceInformation("Adding mod: " + uriModToAdd.ToString()); msgMessager.AddMod(uriModToAdd.ToString()); uriModToAdd = null; } Trace.TraceInformation("Running Application."); try { Application.Run(frmMain); svmServices.ModInstallLog.Backup(); strRequestedGameMode = vmlMainForm.RequestedGameMode; booChangeDefaultGameMode = vmlMainForm.DefaultGameModeChangeRequested; } finally { DisposeServices(svmServices); gmdGameMode.Dispose(); } } } finally { if (mtxGameModeMutex != null) { if (booOwnsMutex) mtxGameModeMutex.ReleaseMutex(); mtxGameModeMutex.Close(); } FileUtil.ForceDelete(m_eifEnvironmentInfo.TemporaryPath); //Clean up created font's. FontManager.Dispose(); } } while (!String.IsNullOrEmpty(strRequestedGameMode) || booChangeDefaultGameMode); return true; }