299 lines
11 KiB
C#
299 lines
11 KiB
C#
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);
|
|
}
|
|
}
|