using BeWoLauncher.Logic.Utils; using BeWoLauncher.ServiceProxy; using BS.SharedLauncher.Information; using System; using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Threading; using System.Windows; using System.Windows.Threading; namespace BeWoLauncher.Logic.Controller { public static class ProcessController { private static Process PlanerProcess { get; set; } public static Application Current => Application.Current; public static LauncherApp CurrentLauncher => Current as LauncherApp; public static bool Running { get; set; } internal static void CheckForOtherInstance() { string procName = Process.GetCurrentProcess().ProcessName; Process[] processes = Process.GetProcessesByName(procName); if (processes.Length > 1) { HandleProzessAlreadyRunning(false); return; } Process[] processes2 = Process.GetProcessesByName("BeWoPlaner"); if (processes2.Length > 0) { HandleProzessAlreadyRunning(false); return; } } internal static void HandleProzessAlreadyRunning(bool letUserKill) { #if DEBUG letUserKill = true; #endif if (letUserKill) { string message = "Möchten Sie es schließen? Dadurch können nicht gespeicherte Daten verloren gehen."; string caption = "BeWo Anwendung läuft bereits. "; var result = MessageBox.Show(message, caption, MessageBoxButton.YesNo); if (result == MessageBoxResult.Yes) { var own_process_id = Process.GetCurrentProcess().Id; GenericTextLogger.Post($"Beende alle BeWo Prozesse außer PID {own_process_id}"); KillAllPlanerProcess(own_process_id); } else { StartLauncherShutdown(); } } else { string message = "Möchten Sie es schließen? Dadurch können nicht gespeicherte Daten verloren gehen."; string caption = "BeWo Anwendung läuft bereits. "; MessageBox.Show(message, caption); StartLauncherShutdown(); } } internal static void StartLauncher() { CheckForOtherInstance(); LauncherServiceFacade.UpdateServerAddresses(); Running = true; } internal static void StartLauncherShutdown() { if (!Running) return; Running = false; GenericTextLogger.Post("Schließe Launcher Prozess..."); Current.Shutdown(); } internal static void StartPlanerProcess() { // based on https://docs.microsoft.com/en-us/dotnet/standard/io/how-to-use-anonymous-pipes-for-local-interprocess-communication?redirectedfrom=MSDN PlanerProcess = new Process(); PlanerProcess.StartInfo.FileName = LauncherPaths.GetPlanerExePath(); PlanerProcess.EnableRaisingEvents = true; PlanerProcess.Exited += PlanerProcess_Exit; using (AnonymousPipeServerStream pipeServer = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable)) { PlanerProcess.StartInfo.Arguments = pipeServer.GetClientHandleAsString(); PlanerProcess.StartInfo.UseShellExecute = false; PlanerProcess.StartInfo.CreateNoWindow = false; PlanerProcess.StartInfo.RedirectStandardOutput = true; PlanerProcess.OutputDataReceived += MessageFromPlanerClient; PlanerProcess.Start(); GenericTextLogger.Post($"Launcher Start: {PlanerProcess.StartInfo.FileName}"); PlanerProcess.BeginOutputReadLine(); pipeServer.DisposeLocalCopyOfClientHandle(); try { using (StreamWriter sw = new StreamWriter(pipeServer)) { var signal = new string[] { "C-137", "C-131" }; sw.AutoFlush = true; SendInfo(sw, signal[0], pipeServer); SessionInformation.Connection.ToList().ForEach(info => SendInfo(sw, info, pipeServer)); SessionInformation.Login.ToList().ForEach(info => SendInfo(sw, info, pipeServer)); SessionInformation.Session.ToList().ForEach(info => SendInfo(sw, info, pipeServer)); SendInfo(sw, signal[1], pipeServer); } } catch (IOException ex) { } } } internal static void SendInfo(StreamWriter sw, string info, AnonymousPipeServerStream pipe) { sw.WriteLine(info); pipe.WaitForPipeDrain(); } internal static void KillOwnPlanerProcess() { if (PlanerProcess is null) return; if (PlanerProcess.HasExited) return; PlanerProcess.CloseMainWindow(); PlanerProcess.Close(); PlanerProcess = null; } internal static void KillAllPlanerProcess(int? own_id) { foreach (var process in Process.GetProcesses()) { if (own_id.HasValue) { if (process.Id == own_id.Value) continue; } if (process.ProcessName.Contains("BeWoPlaner")) { process.Kill(); } } } internal static void PlanerProcess_Exit(object sender, EventArgs e) { // ExitCode Übersicht: // 100 - Nutzer hat Logout in Core gedrückt // 0 - Nutzer hat Fenster geschlossen // 1 - Proess über TaskManager gekillt if (PlanerProcess.ExitCode == 100) { GenericTextLogger.Post("Planer Prozess beendet mit ExitCode 100. Starte Launcher neu."); CurrentLauncher.Dispatcher.BeginInvoke(DispatcherPriority.Render, (Action)delegate { Thread.Sleep(500); ViewController.RestartView(); }); return; } CurrentLauncher.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)StartLauncherShutdown); } private static void MessageFromPlanerClient(object sender, DataReceivedEventArgs args) { var data = args.Data; if (data == "GUI geladen") { ViewController.CurrentWindow.Dispatcher.BeginInvoke(DispatcherPriority.Render, (Action)(() => ViewController.CurrentWindow.Hide())); } } } }