/// <summary> /// Initializes various basic systems like the client's logger, /// constants, and the general exception handler. /// Reads the user's settings from an INI file, /// checks for necessary permissions and starts the client if /// everything goes as it should. /// </summary> /// <param name="parameters">The client's startup parameters.</param> public static void Initialize(StartupParams parameters) { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(HandleExcept); Environment.CurrentDirectory = ProgramConstants.GamePath; CheckPermissions(); Logger.Initialize(ProgramConstants.GamePath + "Client/", "client.log"); Logger.WriteLogFile = true; if (!Directory.Exists(ProgramConstants.GamePath + "Client")) { Directory.CreateDirectory(ProgramConstants.GamePath + "Client"); } File.Delete(ProgramConstants.GamePath + "Client/client.log"); MainClientConstants.Initialize(); Logger.Log("***Logfile for " + MainClientConstants.GAME_NAME_LONG + " client***"); Logger.Log("Client version: " + Application.ProductVersion); // Log information about given startup params if (parameters.NoAudio) { Logger.Log("Startup parameter: No audio"); } if (parameters.MultipleInstanceMode) { Logger.Log("Startup parameter: Allow multiple client instances"); } parameters.UnknownStartupParams.ForEach(p => Logger.Log("Unknown startup parameter: " + p)); Logger.Log("Loading settings."); UserINISettings.Initialize(ClientConfiguration.Instance.SettingsIniName); // Delete obsolete files from old target project versions File.Delete(ProgramConstants.GamePath + "mainclient.log"); File.Delete(ProgramConstants.GamePath + "launchupdt.dat"); try { File.Delete(ProgramConstants.GamePath + "wsock32.dll"); } catch (Exception ex) { MessageBox.Show("Deleting wsock32.dll failed! Please close any " + "applications that could be using the file, and then start the client again." + Environment.NewLine + Environment.NewLine + "Message: " + ex.Message, "CnCNet Client"); Environment.Exit(0); } Application.EnableVisualStyles(); new Startup().Execute(); }
static void Main(string[] args) { bool noAudio = false; bool multipleInstanceMode = false; List <string> unknownStartupParams = new List <string>(); for (int arg = 0; arg < args.Length; arg++) { string argument = args[arg].ToUpper(); switch (argument) { case "-NOAUDIO": // TODO fix throw new NotImplementedException("-NOAUDIO is currently not implemented, please run the client without it."); case "-MULTIPLEINSTANCE": multipleInstanceMode = true; break; default: unknownStartupParams.Add(argument); break; } } StartupParams parameters = new StartupParams(noAudio, multipleInstanceMode, unknownStartupParams); if (multipleInstanceMode) { // Proceed to client startup PreStartup.Initialize(parameters); return; } // We're a single instance application! // http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c/229567 string appGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes( typeof(GuidAttribute), false).GetValue(0)).Value.ToString(); // Global prefix means that the mutex is global to the machine string mutexId = string.Format("Global\\{{{0}}}", appGuid); var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow); var securitySettings = new MutexSecurity(); securitySettings.AddAccessRule(allowEveryoneRule); using (var mutex = new Mutex(false, mutexId, out bool createdNew, securitySettings)) { var hasHandle = false; try { try { hasHandle = mutex.WaitOne(8000, false); if (hasHandle == false) { throw new TimeoutException("Timeout waiting for exclusive access"); } } catch (AbandonedMutexException) { hasHandle = true; } catch (TimeoutException) { return; } // Proceed to client startup PreStartup.Initialize(parameters); } finally { if (hasHandle) { mutex.ReleaseMutex(); } } } }