static void Thread_CheckCrashs() { // version validate if (!SteamApi.GetLatestVersion()) { Global.update = true; Global.tcrash = null; new Thread(Thread_UpdateCSGO).Start(); return; } // Check maps valid if (!string.IsNullOrEmpty(Configs.startmap)) { if (!Configs.game.Equals("insurgency")) { if (!File.Exists(Path.Combine(Path.GetDirectoryName(Configs.srcds), Configs.game, "maps", Configs.startmap + ".bsp"))) { var maps = Directory.GetFiles(Path.Combine(Path.GetDirectoryName(Configs.srcds), Configs.game, "maps"), "*.bsp"); if (maps.Length < 1) { Logger.Error("There are no valid maps in your maps folder. please add maps!"); Console.WriteLine("Press any key to continue ..."); Console.ReadKey(); Environment.Exit(0); } Configs.startmap = Path.GetFileNameWithoutExtension(maps[0]); } } else { var sp = Configs.startmap.Split(' '); if (!File.Exists(Path.Combine(Path.GetDirectoryName(Configs.srcds), Configs.game, "maps", sp[0] + ".bsp"))) { var maps = Directory.GetFiles(Path.Combine(Path.GetDirectoryName(Configs.srcds), Configs.game, "maps"), "*.bsp"); if (maps.Length < 1) { Logger.Error("There are no valid maps in your maps folder. please add maps!"); Console.WriteLine("Press any key to continue ..."); Console.ReadKey(); Environment.Exit(0); } Logger.Log("Not Found startup map: " + Configs.startmap); Configs.startmap = Path.GetFileNameWithoutExtension(maps[0]) + " " + (sp.Length > 1 ? sp[1] : "push"); } else if (sp.Length < 2) { Configs.startmap += " " + (Configs.startmap.Contains("_coop") ? "checkpoint" : "push"); } } } var args = "-console" + " " + "-ip " + Configs.ip + " " + "-port " + Configs.port + " " + "-game \"" + Configs.game + "\" " + "-csm " + version + " " + ((!string.IsNullOrEmpty(Configs.insecure) && int.TryParse(Configs.insecure, out var insecure) && insecure > 0) ? "-insecure " : "") + ((!string.IsNullOrEmpty(Configs.tickrate) && int.TryParse(Configs.tickrate, out var TickRate) && TickRate > 0) ? string.Format("-tickrate {0} ", TickRate) : "") + ((!string.IsNullOrEmpty(Configs.maxplayers) && int.TryParse(Configs.maxplayers, out var maxPlays) && maxPlays > 0) ? string.Format("-maxplayers_override {0} ", maxPlays) : "") + ((!string.IsNullOrEmpty(Configs.nobots) && int.TryParse(Configs.nobots, out var nobotsex) && nobotsex > 0) ? "-nobots " : "") + ((!string.IsNullOrEmpty(Configs.nohltv) && int.TryParse(Configs.nohltv, out var nohltvex) && nohltvex > 0) ? "-nohltv " : "") + ((!string.IsNullOrEmpty(Configs.gametype) && int.TryParse(Configs.gametype, out var gameType) && gameType > 0) ? string.Format("+game_type {0} ", gameType) : "+game_type 0 ") + ((!string.IsNullOrEmpty(Configs.gamemode) && int.TryParse(Configs.gamemode, out var gameMode) && gameMode > 0) ? string.Format("+game_mode {0} ", gameMode) : "") + ((!string.IsNullOrEmpty(Configs.SteamApi)) ? string.Format("-authkey {0} ", Configs.SteamApi) : "") + ((!string.IsNullOrEmpty(Configs.mapgroup)) ? string.Format("+mapgroup {0} ", Configs.mapgroup) : "") + ((!string.IsNullOrEmpty(Configs.startmap)) ? string.Format("+map \"{0}\" ", Configs.startmap) : "") + ((!string.IsNullOrEmpty(Configs.token)) ? string.Format("+sv_setsteamaccount {0} ", Configs.token) : "") + ((!string.IsNullOrEmpty(Configs.groupids)) ? string.Format("+sv_steamgroup {0} ", Configs.groupids) : "") + ((!string.IsNullOrEmpty(Configs.options)) ? Configs.options : "") ; try { Global.srcds = new Process(); Global.srcds.StartInfo.FileName = Configs.srcds; Global.srcds.StartInfo.Arguments = args; Global.srcds.StartInfo.UseShellExecute = false; Global.srcds.EnableRaisingEvents = true; Global.srcds.Exited += new EventHandler(Srcds_OnExited); Global.srcds.Start(); Thread.Sleep(1000); Logger.Log("Srcds Started! -> pid[" + Global.srcds.Id + "] path[" + Global.srcds.MainModule.FileName + "]"); Console.WriteLine(""); Console.WriteLine("Commands: "); Console.WriteLine("show - show srcds console window."); Console.WriteLine("hide - hide srcds console window."); Console.WriteLine("exec - exec command into srcds."); Console.WriteLine("quit - quit srcds and application."); Console.WriteLine("exit - quit srcds and application."); Console.WriteLine("update - force srcds update."); Console.WriteLine("restart - force srcds restart."); Console.Write(Environment.NewLine); Thread.Sleep(6666); if (!currentShow) { Win32Api.Window.Hide(Global.srcds.MainWindowHandle); } // Set to High Global.srcds.PriorityClass = ProcessPriorityClass.High; } catch (Exception e) { Console.WriteLine("SRCDS start failed: {0}", e.Message); Console.WriteLine("StackTrace:{0}{1}", Environment.NewLine, e.StackTrace); Console.ReadKey(false); Environment.Exit(-4); } Global.tupdate = new Thread(Thread_UpdateCheck) { IsBackground = true, Name = "Update Thread" }; Global.tupdate.Start(); Global.crash = false; var a2stimeout = 0u; var srcdsError = string.Empty; while (true) { Thread.Sleep(3000); if (Thread.CurrentThread.ThreadState is System.Threading.ThreadState.AbortRequested || Thread.CurrentThread.ThreadState is System.Threading.ThreadState.Aborted) { return; } if (Global.update) { Global.tcrash = null; return; } srcdsError = SrcdsError(out var errType); if (srcdsError != null) { Logger.Push("Server unexpectedly crashed", errType + ": " + srcdsError); Logger.Log("Srcds crashed -> " + errType + ": " + srcdsError); goto crashed; } if (!A2S.Query(false)) { a2stimeout++; Console.Title = "[TimeOut] " + Global.srcds.MainWindowTitle; } else { if (Global.A2SFireWall) { Console.Title = "[" + Global.currentPlayers + "/" + Global.maximumPlayers + "]" + " - " + Global.hostname; } else { var titles = Encoding.Default.GetBytes(Global.srcds.MainWindowTitle); Console.Title = "[" + Global.currentPlayers + "/" + Global.maximumPlayers + "]" + " - " + Encoding.UTF8.GetString(titles); } tray.notifyIcon.Text = Console.Title; a2stimeout = 0; } if (a2stimeout >= 10) { Logger.Log("Srcds crashed -> A2STimeout"); srcdsError = "Srcds crashed -> A2STimeout"; Logger.Push("Server unexpectedly crashed", "A2S service timeout."); goto crashed; } } // shrot crashed: // clr Global.crash = true; Global.tupdate.Abort(); Global.tcrash = null; // notify icon tray.notifyIcon.BalloonTipTitle = "CSGO Server Manager"; tray.notifyIcon.BalloonTipText = srcdsError ?? "SRCDS crashed!"; tray.notifyIcon.ShowBalloonTip(5000); // check? if (!Global.srcds.HasExited) { Global.srcds.EnableRaisingEvents = false; Global.srcds.Exited -= Srcds_OnExited; Global.srcds.Kill(); } // new tread Thread.Sleep(1500); Global.tcrash = new Thread(Thread_CheckCrashs) { IsBackground = true, Name = "Crash Thread" }; Global.tcrash.Start(); }
static void Main() { // check run once var self = new Mutex(true, Application.StartupPath.GetHashCode().ToString(), out var allow); if (!allow) { MessageBox.Show("CSM is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Environment.Exit(-1); } var myProc = Process.GetCurrentProcess(); myProc.PriorityClass = ProcessPriorityClass.BelowNormal; myHwnd = myProc.MainWindowHandle; // Event Application.ThreadException += ExceptionHandler_CurrentThread; AppDomain.CurrentDomain.UnhandledException += ExceptionHandler_AppDomain; AppDomain.CurrentDomain.ProcessExit += ApplicationHandler_OnExit; SystemEvents.PowerModeChanged += ApplicationHandler_PowerModeChanged; Win32Api.ConsoleCTRL.ConsoleClosed(ApplicationHandler_OnClose); Win32Api.PowerMode.NoSleep(); Console.Title = "CSGO Server Manager v" + version; var conf = Configs.Check(); if (!conf) { Console.WriteLine("{0} >>> Configs was initialized -> You can modify it manually!", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); } Logger.Create(); Helper.WatchFile(); while (!File.Exists(Configs.srcds)) { using (var fileBrowser = new OpenFileDialog()) { fileBrowser.Multiselect = false; fileBrowser.Filter = "CSGO Dedicated Server (srcds.exe)|srcds.exe"; if (fileBrowser.ShowDialog() != DialogResult.OK) { MessageBox.Show("Application Exit!\nYou can modify it manually!", "CSGO Server Manager"); Environment.Exit(0); } else { Configs.srcds = fileBrowser.FileName; Console.WriteLine("{0} >>> Set SRCDS path -> {1}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), Configs.srcds); } } } while (!File.Exists(Configs.steam)) { using (var fileBrowser = new OpenFileDialog()) { fileBrowser.Multiselect = false; fileBrowser.Filter = "SteamCmd (steamcmd.exe)|steamcmd.exe"; if (fileBrowser.ShowDialog() != DialogResult.OK) { MessageBox.Show("Application Exit!\nYou can modify it manually!", "CSGO Server Manager"); Environment.Exit(0); } else { Configs.steam = fileBrowser.FileName; Console.WriteLine("{0} >>> Set Steam path -> {1}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), Configs.steam); } } } if (string.IsNullOrEmpty(Configs.ip) || !IPAddress.TryParse(Configs.ip, out var ipadr)) { do { Console.WriteLine("Please input your Game Server IP ..."); Configs.ip = Console.ReadLine(); }while (!IPAddress.TryParse(Configs.ip, out ipadr)); } if (string.IsNullOrEmpty(Configs.port) || !int.TryParse(Configs.port, out var port)) { do { Console.WriteLine("Please input your Game Server Port (1 - 65535) ..."); Configs.port = Console.ReadLine(); }while (!int.TryParse(Configs.port, out port)); } Global.ipep = new IPEndPoint(ipadr, port); if (!Helper.PortAvailable(port)) { Console.WriteLine("{0} >>> Port[{1}] is unavailable! Finding Application...", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), port); try { var exe = Helper.GetAppByPort(port); Console.WriteLine("{0} >>> Trigger SRCDS Quit -> App[{1}] PID[{2}]", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), exe.MainWindowTitle, exe.Id); Helper.ForceQuit(exe); } catch (Exception e) { Console.WriteLine("{0} >>> Not found Application: {1}", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), e.Message); } } var process = 0; Process.GetProcessesByName("srcds").ToList().ForEach(exe => { if (exe.MainModule.FileName.Equals(Configs.srcds)) { Helper.ForceQuit(exe); Console.WriteLine("{0} >>> Force close old srcds before new srcds start.", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); } process++; }); Console.WriteLine("{0} >>> {1} SRCDS are running on current host.", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), process); if (!string.IsNullOrEmpty(Configs.TokenApi)) { while (TokenApi.CheckTokens(true) <= 0) { Console.WriteLine("{0} >>> TokenApi -> Checking ...", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); } Console.WriteLine("{0} >>> TokenApi -> feature is available.", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); new Thread(Thread_CheckToken).Start(); } else { Console.WriteLine("{0} >>> TokenApi -> ApiKey was not found.", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")); } // Open editor? if (string.IsNullOrEmpty(Configs.token) && !conf) { Console.WriteLine("Do you want to edit server config manually? [Y/N]"); if (Console.ReadKey().Key == ConsoleKey.Y) { Process proc = null; try { proc = Process.Start(new ProcessStartInfo() { FileName = "notepad++.exe", Arguments = " \"" + Path.Combine(Application.StartupPath, "server_config.ini") + "\" ", WindowStyle = ProcessWindowStyle.Minimized }); MessageBox.Show("Please Edit server config in Notepad++!" + Environment.NewLine + "Don't forget to click save button!", "CSGO Server Manager", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } catch { if (File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kxnrl", "Notepad", "notepad++.exe"))) { proc = Process.Start(new ProcessStartInfo() { FileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kxnrl", "Notepad", "notepad++.exe"), Arguments = " \"" + Path.Combine(Application.StartupPath, "server_config.ini") + "\" ", WindowStyle = ProcessWindowStyle.Minimized }); MessageBox.Show("Please Edit server config in Notepad++!" + Environment.NewLine + "Don't forget to click save button!", "CSGO Server Manager", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { proc = Process.Start(new ProcessStartInfo() { FileName = "notepad.exe", Arguments = " \"" + Path.Combine(Application.StartupPath, "server_config.ini") + "\" ", WindowStyle = ProcessWindowStyle.Minimized }); MessageBox.Show("Please Edit server config in Notepad!" + Environment.NewLine + "Don't forget to click save button!", "CSGO Server Manager", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } } finally { if (proc != null) { // reverse Win32Api.Window.Show(proc.MainWindowHandle); Win32Api.Window.Active(proc.MainWindowHandle); } Environment.Exit(0); } } } // check a2s key A2S.CheckFirewall(); // check server chan Logger.Check(); // current Win32Api.Window.Hide(myHwnd); currentShow = false; Global.tcrash = new Thread(Thread_CheckCrashs) { IsBackground = true, Name = "Crash Thread" }; Global.tcrash.Start(); new Thread(() => { tray.notifyMenu = new ContextMenu(); tray.showHide = new MenuItem("Show"); tray.exitButton = new MenuItem("Exit"); tray.notifyMenu.MenuItems.Add(0, tray.showHide); tray.notifyMenu.MenuItems.Add(1, tray.exitButton); tray.notifyIcon = new NotifyIcon() { BalloonTipIcon = ToolTipIcon.Info, ContextMenu = tray.notifyMenu, Text = "CSGO Server Manager", Icon = Properties.Resources.lilia, Visible = true, }; tray.showHide.Click += new EventHandler(ApplicationHandler_TrayIcon); tray.exitButton.Click += new EventHandler(ApplicationHandler_TrayIcon); Application.Run(); }).Start(); Thread.Sleep(5000); tray.notifyIcon.BalloonTipTitle = "CSGO Server Manager"; tray.notifyIcon.BalloonTipText = "Server Started!"; tray.notifyIcon.ShowBalloonTip(5000); while (true) { var input = Console.ReadLine(); if (Global.update) { Console.WriteLine("Updating ..."); continue; } if (Global.crash) { Console.WriteLine("Restarting ..."); continue; } switch (input.ToLower()) { case "show": Win32Api.Window.Show(Global.srcds.MainWindowHandle); Console.WriteLine("Show SRCDS window."); break; case "hide": Win32Api.Window.Hide(Global.srcds.MainWindowHandle); Console.WriteLine("Hide SRCDS window."); break; case "quit": Environment.Exit(0); break; case "exit": Environment.Exit(0); break; case "update": for (var cd = 60; cd > 0; cd--) { Console.WriteLine("Server restart in " + cd + " seconds"); Win32Api.Message.Write(Global.srcds.MainWindowHandle, "say Server restart in " + cd + " seconds"); Win32Api.Message.Send(Global.srcds.MainWindowHandle); Thread.Sleep(1000); if (Global.crash) { break; } } Logger.Log("Trigger server update."); Global.update = true; Global.tupdate.Abort(); Global.tupdate = null; new Thread(Thread_UpdateCSGO).Start(); break; case "restart": Logger.Log("Trigger server restart."); Global.tupdate.Abort(); Global.tcrash.Abort(); Global.tupdate = null; Global.tcrash = null; Global.srcds.EnableRaisingEvents = false; Global.srcds.Exited -= Srcds_OnExited; Helper.KillSRCDS(true); Global.tcrash = new Thread(Thread_CheckCrashs) { IsBackground = true, Name = "Crash Thread" }; Global.tcrash.Start(); break; default: if (input.StartsWith("exec ")) { input = input.Replace("exec ", ""); if (input.Length > 1) { Win32Api.Message.Write(Global.srcds.MainWindowHandle, input); Win32Api.Message.Send(Global.srcds.MainWindowHandle); Logger.Log("Execute server command: " + input); } else { Console.WriteLine("Command is invalid."); } } else { Console.WriteLine("Commands: "); Console.WriteLine("show - show srcds console window."); Console.WriteLine("hide - hide srcds console window."); Console.WriteLine("exec - exec command into srcds."); Console.WriteLine("quit - quit srcds and application."); Console.WriteLine("exit - quit srcds and application."); Console.WriteLine("update - force srcds update."); Console.WriteLine("restart - force srcds restart."); } break; } } }