SafeDispatch/AppServer/Program.cs

299 lines
11 KiB
C#
Raw Permalink Normal View History

2024-02-22 16:43:59 +00:00
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);
}
}