222 lines
8.6 KiB
C#
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
|
|
|
|
}
|
|
}
|