using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows; using System.Windows.Data; using System.Windows.Media; using Comal.Classes; using InABox.Configuration; using InABox.Core; using InABox.Logging; using InABox.WPF; using InABox.WPF.Themes; using NDesk.Options; using PRSDesktop; using Syncfusion.Licensing; using Path = System.IO.Path; namespace PRSDesktop { /// /// Interaction logic for App.xaml /// public partial class App : Application { public static DatabaseSettings DatabaseSettings; public static AutoUpdateSettings AutoUpdateSettings; public static Guid EmployeeID = Guid.Empty; public static String EmployeeName = ""; public static String EmployeeEmail = ""; public static string Profile = ""; public static bool IsClosing = false; /*/ Guid to ensure that only one instance of PRS is running public static Guid AppGuid = Guid.Parse("237E8828-7F5A-4298-B311-CF0FC27882EC"); private static Mutex AppMutex;*/ private readonly OptionSet _commandLineParameters = new() { { "profile=", "", p => { Profile = p; } } }; public App() { SyncfusionLicenseProvider.RegisterLicense(CoreUtils.SyncfusionLicense(SyncfusionVersion.v20_2)); } private void AutoDiscover(Dictionary allsettings) { var confirm = MessageBox.Show("Try to configure Server Connection Automatically?", "Auto Discover", MessageBoxButton.YesNoCancel); if (confirm == MessageBoxResult.Yes) try { using (new WaitCursor()) { AutoDiscoverySettings autodiscover; using (var client = new UdpClient()) { client.Client.SendTimeout = 10000; client.Client.ReceiveTimeout = 20000; var requestData = Encoding.ASCII.GetBytes(""); var serverEndPoint = new IPEndPoint(IPAddress.Any, 0); client.EnableBroadcast = true; client.Send(requestData, requestData.Length, new IPEndPoint(IPAddress.Broadcast, 8888)); var serverResponseData = client.Receive(ref serverEndPoint); var serverResponse = Encoding.ASCII.GetString(serverResponseData); autodiscover = Serialization.Deserialize(serverResponse); client.Close(); } var settings = new DatabaseSettings(); settings.IsActive = true; settings.Logo = autodiscover.Logo; settings.Protocol = autodiscover.Protocol; settings.DatabaseType = DatabaseType.Networked; settings.URLs = autodiscover.URLs; settings.LibraryLocation = autodiscover.LibraryLocation; settings.GoogleAPIKey = autodiscover.GoogleAPIKey; allsettings[autodiscover.Name] = settings; new LocalConfiguration(autodiscover.Name).Save(settings); AutoUpdateSettings = new AutoUpdateSettings { Channel = autodiscover.UpdateChannel, Type = autodiscover.UpdateType, Location = autodiscover.UpdateLocation, Elevated = autodiscover.UpdateAdmin }; new LocalConfiguration().Save(AutoUpdateSettings); MessageBox.Show($"Server found at {String.Join(";",autodiscover.URLs)}"); } } catch { MessageBox.Show("No Server Found"); } } private void MoveDirectory(string[] source, string target) { var stack = new Stack(); stack.Push(new Folders(source[0], target)); while (stack.Count > 0) { var folders = stack.Pop(); Directory.CreateDirectory(folders.Target); foreach (var file in Directory.GetFiles(folders.Source, "*.*")) { var targetFile = Path.Combine(folders.Target, Path.GetFileName(file)); if (!File.Exists(targetFile)) File.Move(file, targetFile); else File.Delete(file); } foreach (var folder in Directory.GetDirectories(folders.Source)) stack.Push(new Folders(folder, Path.Combine(folders.Target, Path.GetFileName(folder)))); } Directory.Delete(source[0], true); } public static void SaveDatabaseSettings() { new LocalConfiguration(Profile).Save(DatabaseSettings); } protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); /*AppMutex = new Mutex(false, $"Global\\{AppGuid}"); // Don't open if PRS is already running. if(!AppMutex.WaitOne(0, false)) { Shutdown(0); SendToProcesses(Message.Maximise); return; }*/ AutoUpdateSettings = new LocalConfiguration().Load(); var oldPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Comal.Desktop"); if (Directory.Exists(oldPath)) MoveDirectory(new[] { oldPath }, CoreUtils.GetPath()); ShutdownMode = ShutdownMode.OnExplicitShutdown; SetupExceptionHandling(); MainLogger.AddLogger(new LogFileLogger(CoreUtils.GetPath())); Logger.OnLog += MainLogger.Send; if (e.Args.Any()) { DatabaseSettings = new DatabaseSettings(); var extras = _commandLineParameters.Parse(e.Args); if (extras.Any()) { var sw = new StringWriter(); sw.WriteLine("Unknown Parameter(s) found:"); foreach (var extra in extras) sw.WriteLine(" " + extra); sw.WriteLine(); sw.WriteLine("The following parameters are valid:"); _commandLineParameters.WriteOptionDescriptions(sw); MessageBox.Show(sw.ToString(), "PRS Desktop Startup Options"); } } bool bSaveSettings = false; var allsettings = new LocalConfiguration().LoadAll(); // Try AutoDiscovery if (!allsettings.Any()) AutoDiscover(allsettings); // Create Default Database Entry if (!allsettings.Any()) { allsettings["Default"] = new DatabaseSettings(); bSaveSettings = true; } // Convert Blank Key to "Default" if (allsettings.ContainsKey("")) { var defaultSettings = allsettings[""]; allsettings.Remove(""); defaultSettings.IsActive = true; allsettings["Default"] = defaultSettings; bSaveSettings = true; } // Check and Convert from URL + Port => URLs foreach (var key in allsettings.Keys) { var settings = allsettings[key]; var oldurl = CoreUtils.GetPropertyValue(settings, "URL") as String; var oldport = CoreUtils.GetPropertyValue(settings, "Port"); if (!String.IsNullOrWhiteSpace(oldurl)) { bSaveSettings = true; settings.URLs = new String[] { $"{oldurl}:{oldport}" }; CoreUtils.SetPropertyValue(settings, "URL", ""); CoreUtils.SetPropertyValue(settings, "Port", 0); } if (settings.URLs != null) { var urls = new List(); foreach (var url in settings.URLs) { var comps = url.Split(new[] { "://" }, StringSplitOptions.RemoveEmptyEntries); if (comps.Length > 1) { bSaveSettings = true; urls.Add(comps.Last()); } else urls.Add(url); } settings.URLs = urls.ToArray(); } } if (bSaveSettings) new LocalConfiguration().SaveAll(allsettings); DatabaseSettings = null; if (!string.IsNullOrWhiteSpace(Profile)) { if (allsettings.ContainsKey(Profile)) DatabaseSettings = allsettings[Profile]; else MessageBox.Show(string.Format("Profile {0} does not exist!", Profile)); } if (DatabaseSettings == null) { var keys = allsettings.Keys.Where(x => allsettings[x].IsActive).ToArray(); if (keys.Length > 1) { var form = new SelectDatabase(allsettings); if (form.ShowDialog() == true) { Profile = form.Database; DatabaseSettings = allsettings[form.Database]; } else { Shutdown(1); return; } form = null; } else { Profile = keys.First(); DatabaseSettings = allsettings.Values.First(); } } StartupUri = new Uri("MainWindow.xaml", UriKind.Relative); } protected override void OnExit(ExitEventArgs e) { base.OnExit(e); //AppMutex.ReleaseMutex(); } private void SetupExceptionHandling() { AppDomain.CurrentDomain.UnhandledException += (s, e) => LogUnhandledException((Exception)e.ExceptionObject, "AppDomain.CurrentDomain.UnhandledException"); DispatcherUnhandledException += (s, e) => { LogUnhandledException(e.Exception, "Application.Current.DispatcherUnhandledException"); e.Handled = true; }; } private void LogUnhandledException(Exception exception, string source) { var messages = new List(); var e2 = exception; while (e2 != null) { messages.InsertRange(0, new[] { e2.Message, e2.StackTrace, "============================================" }); e2 = e2.InnerException; } MainLogger.Send(LogType.Error, "", string.Join("\n", messages)); // if (exception.Message.StartsWith("Dispatcher processing has been suspended")) // try // { // SendKeys.Send("{ESC}"); // } // catch (Exception e) // { // } } private class Folders { public Folders(string source, string target) { Source = source; Target = target; } public string Source { get; } public string Target { get; } } /* public enum Message { Maximise = 0x2A76 } private void SendToProcesses(Message message) { var process = Process.GetCurrentProcess(); var processes = Process.GetProcessesByName(process.ProcessName); if(processes.Length > 1) { foreach(var p in processes) { if(p.Id != process.Id) { SendMessage(p.MainWindowHandle, (uint)message, IntPtr.Zero, IntPtr.Zero); } } } } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SendMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam); */ } }