Files
LogDashboard/Source/LogDashboard.UI/App.xaml.cs
2025-06-13 13:21:12 -07:00

222 lines
8.6 KiB
C#

//******************************************************************************//
// App.xaml.cs
// 12/4/2023
//
// RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
// PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
// AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
// UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
// RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
// CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
// OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
// COMPANY.
//
// THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S. GOVERNMENT
//
// UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//
// WARNING: THIS DOCUMENT CONTAINS TECHNICAL DATA AND / OR TECHNOLOGY WHOSE
// EXPORT OR DISCLOSURE TO NON-U.S. PERSONS, WHEREVER LOCATED, IS RESTRICTED
// BY THE INTERNATIONAL TRAFFIC IN ARMS REGULATIONS (ITAR) (22 C.F.R. SECTION
// 120-130) OR THE EXPORT ADMINISTRATION REGULATIONS (EAR) (15 C.F.R. SECTION
// 730-774). THIS DOCUMENT CANNOT BE EXPORTED (E.G., PROVIDED TO A SUPPLIER
// OUTSIDE OF THE UNITED STATES) OR DISCLOSED TO A NON-U.S. PERSON, WHEREVER
// LOCATED, UNTIL A FINAL JURISDICTION AND CLASSIFICATION DETERMINATION HAS
// BEEN COMPLETED AND APPROVED BY RAYTHEON, AND ANY REQUIRED U.S. GOVERNMENT
// APPROVALS HAVE BEEN OBTAINED. VIOLATIONS ARE SUBJECT TO SEVERE CRIMINAL
// PENALTIES.
//
// DOD 5220.22-M, INDUSTRIAL SECURITY MANUAL, CHAPTER 5, SECTION 1 THROUGH 9 :
// FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN OR DOD 5200.1-R,
// INFORMATION SECURITY PROGRAM, CHAPTER 6. FOR UNCLASSIFIED, LIMITED DOCUMENTS
// DESTROY BY ANY METHOD THAT WILL PREVENT DISCLOSURE OF CONTENTS OR
// RECONSTRUCTION OF THE DOCUMENT.
// POC: Alex Kravchenko (1118268)
//******************************************************************************//
using Microsoft.Win32;
using NLog;
using Raytheon.LogDashboard.Helpers;
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.IO;
using Raytheon.LogDashboard.View;
using GalaSoft.MvvmLight.Messaging;
using System.Reflection;
namespace LogDashboard
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
public static bool IsManualStartup { get; private set; } = false;
public ResourceDictionary ThemeDictionary => Resources.MergedDictionaries[1];
public void ChangeTheme(Uri uri)
{
ThemeDictionary.MergedDictionaries[1] = new ResourceDictionary { Source = uri };
}
static Mutex mutex = new Mutex(true, "{8F6F0AC4-B9A1-45fd-A8CF-72F04E6BDE8F}");
[STAThread]
protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
if(e.Args.Any(x => (x.EndsWith(".txt") || x.EndsWith(".log")) && File.Exists(x)))
{
IsManualStartup = true;
try
{
if(!mutex.WaitOne(TimeSpan.Zero, true))
{
Process proc = Process.GetCurrentProcess();
string processName = proc.ProcessName.Replace(".vshost", "");
var runningProcess = Process.GetProcesses()
.FirstOrDefault(x => (x.ProcessName == processName || x.ProcessName == proc.ProcessName || x.ProcessName == proc.ProcessName + ".vshost") && x.Id != proc.Id);
if(runningProcess == null)
{
App app = new App();
app.InitializeComponent();
MainWindow window = new MainWindow();
Raytheon.LogDashboard.View.MainWindow.HandleParameter(e.Args);
app.Run(window);
return;
}
UnsafeNative.SendMessage(runningProcess.MainWindowHandle, string.Join(" ", e.Args));
Environment.Exit(0);
}
}
catch(Exception exception)
{
logger.Warn(exception, "OnStartup check exception (open with arguments)");
}
}
string assemblyFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string logDashboardConfigFilePath = Path.Combine(assemblyFolder, "LogDashboard.xml");
// load settings from configuration file
Raytheon.LogDashboard.Model.Settings.SetInstance(logDashboardConfigFilePath).Load();
if(Raytheon.LogDashboard.Model.Settings.Instance.OnlyOneAppInstance)
{
try
{
if(mutex.WaitOne(TimeSpan.Zero, true))
{
mutex.ReleaseMutex();
}
else
{
logger.Trace("OnStartup: one instance of Log Viewer already started");
Messenger.Default.Send("OnStartup: one instance of Log Viewer already started", "DisplayCustomMessage");
Environment.Exit(0);
}
}
catch(Exception exception)
{
logger.Warn(exception, "OnStartup check exception");
}
}
try
{
if(!IsAssociated())
{
string filePath = Process.GetCurrentProcess().MainModule.FileName;
SetAssociation(".txt", "LogDashboard", filePath);
SetAssociation(".log", "LogDashboard", filePath);
SetAssociation(".csv", "LogDashboard", filePath);
}
}
catch(Exception exception)
{
logger.Warn(exception, "OnStartup set file association exception");
}
base.OnStartup(e);
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
logger.Fatal($"Unhandled exception {e.ExceptionObject as Exception}");
Environment.Exit(1);
}
private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
logger.Fatal($"Unhandled Exception: {e.Exception}");
Environment.Exit(2);
}
#region File Association
private bool IsAssociated()
{
return Registry.CurrentUser.OpenSubKey(@"Software\Classes\LogViewer", false) != null;
}
[DllImport("Shell32.dll")]
private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
private const int SHCNE_ASSOCCHANGED = 0x8000000;
private const int SHCNF_FLUSH = 0x1000;
private void SetAssociation(string extension, string progId, string applicationFilePath)
{
bool madeChanges = false;
madeChanges |= SetKeyDefaultValue($@"Software\Classes\{progId}\shell\open\command", "\"" + applicationFilePath + "\" \"%1\"");
madeChanges |= SetProgIdValue($@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\{extension}\OpenWithProgids", progId);
if(madeChanges)
{
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
}
}
private bool SetProgIdValue(string path, string progId)
{
using(var key = Registry.CurrentUser.CreateSubKey(path))
{
if(key.GetValueNames().All(x => x != progId))
{
key.SetValue(progId, Encoding.Unicode.GetBytes(string.Empty), RegistryValueKind.Binary);
return true;
}
}
return false;
}
private bool SetKeyDefaultValue(string keyPath, string value)
{
using(var key = Registry.CurrentUser.CreateSubKey(keyPath))
{
if(key.GetValue(null) as string != value)
{
key.SetValue(null, value);
return true;
}
}
return false;
}
#endregion
}
}