using System; using System.Linq; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Diagnostics; using System.Threading; using SafeMobileLib; using System.IO; using SafeMobileLib.Helpers; using System.ServiceProcess; using System.IO.Pipes; namespace AppServer { class Program { public static string SERVICE_NAME = "AppServerWatchDog"; public static Config cfg; public static bool isRunning = true; public static bool isConsoleEnabled = false; public static String COMPANY = "SafeMobile"; public static bool SHOULD_LOAD = true; public static string[] cmdArgs; static MainForm MainWindow = null; static String filename = ""; static void Main(string[] args) { cmdArgs = args; #if SIMOCO COMPANY = "Simoco"; #else COMPANY = "SafeMobile"; #endif // load configs cfg = new Config(); // parse the command line args CommandLineHelper clh = new CommandLineHelper(args, Console.Title); Console.Title = "AppServerConsole"; // register for console events in order to intercept the close event handler = new ConsoleEventDelegate(ConsoleEventCallback); SetConsoleCtrlHandler(handler, true); // minimize the console SendMessage(Process.GetCurrentProcess().MainWindowHandle, WM_SYSCOMMAND, SC_MINIMIZE, 0); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); if (!AppDomain.CurrentDomain.FriendlyName.EndsWith("vshost.exe")) { Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); // Set the unhandled exception mode to force all Windows Forms errors // to go through our handler. Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); } // customize the new FeedbackRadMessageBox FeedbackRadMessageBox.InteractionWaitSeconds = 7; FeedbackRadMessageBox.SetTheme("TelerikMetroBlue"); MainWindow = new MainForm(); if (SHOULD_LOAD) { if (cfg.watchdog) { String serviceLocation = System.Reflection.Assembly.GetExecutingAssembly().Location; String serviceFolder = serviceLocation.Substring(0, serviceLocation.LastIndexOf('\\')); if (!IsServiceInstalled("AppServerWatchDogService")) InstallService("AppServerWatchDogService", 1000, serviceFolder); // start watchdog thread Thread t = new Thread(WatchDogThread); t.Start(); // kill any previous instance of watchDog just to be sure KillWatchDog(); //start watchdog ServiceControlUtils.startService("AppServerWatchDogService"); } else { if (IsServiceInstalled("AppServerWatchDogService")) UninstallService("AppServerWatchDogService", 1000); } Application.Run(MainWindow); } } private static void WatchDogThread() { while (isRunning) { // check if the app server is running using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("appServerPipe", PipeDirection.InOut)) { // Wait for a client to connect pipeServer.WaitForConnection(); Utils.WriteLine("WatchDog connected: " + LocationThread.LocationCheckQueuesCount); try { // Read user input and send that to the client process. using (StreamWriter sw = new StreamWriter(pipeServer)) { sw.AutoFlush = true; sw.WriteLine(LocationThread.LocationCheckQueuesCount + "|" + MainForm.LocationQueue.Count + "|" + MainForm.prevLocationQueue.Count); LocationThread.LocationCheckQueuesCount = 0; } } // Catch the IOException that is raised if the pipe is broken // or disconnected. catch (IOException e) { Utils.WriteLine($"ERROR: {e.Message}",ConsoleColor.Red); } } } } public static bool IsServiceInstalled(string serviceName) { ServiceController ctl = ServiceController.GetServices() .FirstOrDefault(s => s.ServiceName == serviceName); return ctl != null; } public static bool UninstallService(string serviceName, int timeoutMilliseconds) { return ChangeService(serviceName, false); } public static void InstallService(string serviceName, int timeoutMilliseconds, string path) { ChangeService(serviceName, true, path); } private static bool ChangeService(String serviceName, bool isInstall, string path = "") { String cmd = $"sc {(isInstall ? $"create {serviceName} binPath=\"{path}\\{serviceName}.exe\" start= auto" : $"delete {serviceName}")}"; Process p = new Process(); ProcessStartInfo info = new ProcessStartInfo(); info.CreateNoWindow = true; info.FileName = "cmd.exe"; info.RedirectStandardInput = true; info.RedirectStandardOutput = true; info.UseShellExecute = false; p.StartInfo = info; p.Start(); using (StreamWriter sw = p.StandardInput) { if (sw.BaseStream.CanWrite) { sw.WriteLine(cmd); Utils.WriteLine($"{(isInstall ? "Installing" : "Uninstalling")} {serviceName}: {cmd}", ConsoleColor.DarkYellow); } sw.Close(); p.WaitForExit(); } using (StreamReader reader = p.StandardOutput) { string output = reader.ReadToEnd(); return true; //Console.WriteLine(output); //Utils.WriteLine($"{(isInstall ? "Installing" : "Uninstalling")} AppServerWatchDog OUTPUT RESULT " + output, ConsoleColor.Magenta); } } public static void KillWatchDog() { ServiceControlUtils.stopService("AppServerWatchDogService"); } static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { Utils.WriteLine("Application_ThreadException " + e.ToString()); // here you can log the exception ... Utils.WriteEventLog("AppServer", "ThreadException : " + e.Exception.ToString(), EventLogEntryType.Error, 401); MainForm.isRunning = false; Thread.Sleep(2000); try { MainForm.udp.Send(SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#4#Application server stopped#"), Utils.Convert_text_For_multicast("#0.0#210#4#Application server stopped#").Length); // save all unhandled gps positions MainForm.DumpLocationQueueToFile(); } catch (Exception ex2) { Utils.WriteLine(ex2.ToString(), ConsoleColor.Red); } } static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Utils.WriteLine("CurrentDomain_UnhandledException " + (e.ExceptionObject as Exception).ToString()); //FeedbackRadMessageBox.ShowError((e.ExceptionObject as Exception).ToString(), "Unhandled UI Exception AppServer.Please restart the application."); // here you can log the exception ... Utils.WriteEventLog("AppServer", "UnhandledException : " + (e.ExceptionObject as Exception).ToString(), EventLogEntryType.Error, 402); MainForm.isRunning = false; Thread.Sleep(2000); try { MainForm.udp?.Send(SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#4#Application server stopped#"), SafeMobileLib.Utils.Convert_text_For_multicast("#0.0#210#4#Application server stopped#").Length); // save all unhandled gps positions MainForm.DumpLocationQueueToFile(); // restart app //RestartApp((e.ExceptionObject as Exception).ToString()); } catch (Exception ex2) { //SM.Debug("Error on sending Message to SD that APPServer has problem: " + ex2.ToString()); Utils.WriteLine(ex2.ToString(), ConsoleColor.Red); } } [DllImport("user32.dll")] internal static extern bool SendMessage(IntPtr hWnd, Int32 msg, Int32 wParam, Int32 lParam); static Int32 WM_SYSCOMMAND = 0x0112; static Int32 SC_MINIMIZE = 0x0F020; static bool ConsoleEventCallback(int eventType) { int CTRL_C_EVENT = 0; int CTRL_BREAK_EVENT = 1; int CTRL_CLOSE_EVENT = 2; int CTRL_LOGOFF_EVENT = 5; int CTRL_SHUTDOWN_EVENT = 6; if (eventType == CTRL_C_EVENT || eventType == CTRL_BREAK_EVENT || eventType == CTRL_CLOSE_EVENT || eventType == CTRL_LOGOFF_EVENT || eventType == CTRL_SHUTDOWN_EVENT) { Console.WriteLine("Console window closing, death imminent"); // check if the main form was initiated and an invoke is required if (MainWindow != null && MainWindow.InvokeRequired) { // call the Close event for the Main form using an invoke because it is called // from another thread MainWindow.Invoke((MethodInvoker)delegate() { MainWindow.Close(); }); } } return false; } static ConsoleEventDelegate handler; // Keeps it from getting garbage collected // Pinvoke private delegate bool ConsoleEventDelegate(int eventType); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add); } }