diff options
Diffstat (limited to 'MediaBrowser.ServerApplication/App.xaml.cs')
| -rw-r--r-- | MediaBrowser.ServerApplication/App.xaml.cs | 326 |
1 files changed, 300 insertions, 26 deletions
diff --git a/MediaBrowser.ServerApplication/App.xaml.cs b/MediaBrowser.ServerApplication/App.xaml.cs index 4da5c39fe..cc6367127 100644 --- a/MediaBrowser.ServerApplication/App.xaml.cs +++ b/MediaBrowser.ServerApplication/App.xaml.cs @@ -1,23 +1,31 @@ using MediaBrowser.Common.Kernel; -using MediaBrowser.Common.Logging; -using MediaBrowser.Common.UI; +using MediaBrowser.Common.Updates; using MediaBrowser.Controller; using MediaBrowser.IsoMounter; +using MediaBrowser.Logging.Nlog; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Uninstall; using MediaBrowser.ServerApplication.Implementations; +using Microsoft.Win32; using System; -using System.Collections.Generic; +using System.Deployment.Application; using System.Diagnostics; +using System.IO; using System.Linq; +using System.Net.Cache; +using System.Threading; +using System.Threading.Tasks; using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Media.Imaging; namespace MediaBrowser.ServerApplication { /// <summary> /// Interaction logic for App.xaml /// </summary> - public partial class App : BaseApplication, IApplication + public partial class App : Application, IApplicationHost { /// <summary> /// Defines the entry point of the application. @@ -25,8 +33,7 @@ namespace MediaBrowser.ServerApplication [STAThread] public static void Main() { - var application = new App(LogManager.GetLogger("App")); - application.InitializeComponent(); + var application = new App(new NLogger("App")); application.Run(); } @@ -44,20 +51,44 @@ namespace MediaBrowser.ServerApplication } /// <summary> + /// The single instance mutex + /// </summary> + private Mutex SingleInstanceMutex; + + /// <summary> + /// Gets or sets the kernel. + /// </summary> + /// <value>The kernel.</value> + protected IKernel Kernel { get; set; } + + /// <summary> + /// Gets or sets the logger. + /// </summary> + /// <value>The logger.</value> + protected ILogger Logger { get; set; } + + /// <summary> + /// Gets or sets the log file path. + /// </summary> + /// <value>The log file path.</value> + private string LogFilePath { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="App" /> class. /// </summary> /// <param name="logger">The logger.</param> public App(ILogger logger) - : base(logger) { - + Logger = logger; + + InitializeComponent(); } /// <summary> /// Gets the name of the product. /// </summary> /// <value>The name of the product.</value> - protected override string ProductName + protected string ProductName { get { return Globals.ProductName; } } @@ -66,7 +97,7 @@ namespace MediaBrowser.ServerApplication /// Gets the name of the publisher. /// </summary> /// <value>The name of the publisher.</value> - protected override string PublisherName + protected string PublisherName { get { return Globals.PublisherName; } } @@ -75,7 +106,7 @@ namespace MediaBrowser.ServerApplication /// Gets the name of the suite. /// </summary> /// <value>The name of the suite.</value> - protected override string SuiteName + protected string SuiteName { get { return Globals.SuiteName; } } @@ -84,21 +115,180 @@ namespace MediaBrowser.ServerApplication /// Gets the name of the uninstaller file. /// </summary> /// <value>The name of the uninstaller file.</value> - protected override string UninstallerFileName + protected string UninstallerFileName { get { return "MediaBrowser.Server.Uninstall.exe"; } } /// <summary> - /// Called when [second instance launched]. + /// Gets or sets a value indicating whether [last run at startup value]. /// </summary> - /// <param name="args">The args.</param> - protected override void OnSecondInstanceLaunched(IList<string> args) + /// <value><c>null</c> if [last run at startup value] contains no value, <c>true</c> if [last run at startup value]; otherwise, <c>false</c>.</value> + private bool? LastRunAtStartupValue { get; set; } + + /// <summary> + /// Raises the <see cref="E:System.Windows.Application.Startup" /> event. + /// </summary> + /// <param name="e">A <see cref="T:System.Windows.StartupEventArgs" /> that contains the event data.</param> + protected override void OnStartup(StartupEventArgs e) { - base.OnSecondInstanceLaunched(args); + bool createdNew; + SingleInstanceMutex = new Mutex(true, @"Local\" + GetType().Assembly.GetName().Name, out createdNew); + if (!createdNew) + { + SingleInstanceMutex = null; + Shutdown(); + return; + } - OpenDashboard(); - InitializeComponent(); + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + LoadKernel(); + + SystemEvents.SessionEnding += SystemEvents_SessionEnding; + } + + /// <summary> + /// Handles the UnhandledException event of the CurrentDomain control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="UnhandledExceptionEventArgs" /> instance containing the event data.</param> + void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + var exception = (Exception)e.ExceptionObject; + + Logger.ErrorException("UnhandledException", exception); + + MessageBox.Show("Unhandled exception: " + exception.Message); + } + + /// <summary> + /// Handles the SessionEnding event of the SystemEvents control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="SessionEndingEventArgs" /> instance containing the event data.</param> + void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) + { + // Try to shut down gracefully + Shutdown(); + } + + /// <summary> + /// Loads the kernel. + /// </summary> + protected async void LoadKernel() + { + Kernel = new Kernel(this, new PismoIsoManager(Logger), new DotNetZipClient(), new BdInfoExaminer(), Logger); + + try + { + new MainWindow(Logger).Show(); + + var now = DateTime.UtcNow; + + await Kernel.Init(); + + var done = (DateTime.UtcNow - now); + Logger.Info("Kernel.Init completed in {0}{1} minutes and {2} seconds.", done.Hours > 0 ? done.Hours + " Hours " : "", done.Minutes, done.Seconds); + + await OnKernelLoaded(); + } + catch (Exception ex) + { + Logger.ErrorException("Error launching application", ex); + + MessageBox.Show("There was an error launching Media Browser: " + ex.Message); + + // Shutdown the app with an error code + Shutdown(1); + } + } + + /// <summary> + /// Called when [kernel loaded]. + /// </summary> + /// <returns>Task.</returns> + protected Task OnKernelLoaded() + { + return Task.Run(() => + { + Kernel.ConfigurationUpdated += Kernel_ConfigurationUpdated; + + ConfigureClickOnceStartup(); + }); + } + + /// <summary> + /// Handles the ConfigurationUpdated event of the Kernel control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> + void Kernel_ConfigurationUpdated(object sender, EventArgs e) + { + if (!LastRunAtStartupValue.HasValue || LastRunAtStartupValue.Value != Kernel.Configuration.RunAtStartup) + { + ConfigureClickOnceStartup(); + } + } + + /// <summary> + /// Configures the click once startup. + /// </summary> + private void ConfigureClickOnceStartup() + { + if (!ApplicationDeployment.IsNetworkDeployed) + { + return; + } + + try + { + var clickOnceHelper = new ClickOnceHelper(PublisherName, ProductName, SuiteName); + + if (Kernel.Configuration.RunAtStartup) + { + clickOnceHelper.UpdateUninstallParameters(UninstallerFileName); + clickOnceHelper.AddShortcutToStartup(); + } + else + { + clickOnceHelper.RemoveShortcutFromStartup(); + } + + LastRunAtStartupValue = Kernel.Configuration.RunAtStartup; + } + catch (Exception ex) + { + Logger.ErrorException("Error configuring ClickOnce", ex); + } + } + + /// <summary> + /// Raises the <see cref="E:System.Windows.Application.Exit" /> event. + /// </summary> + /// <param name="e">An <see cref="T:System.Windows.ExitEventArgs" /> that contains the event data.</param> + protected override void OnExit(ExitEventArgs e) + { + ReleaseMutex(); + + base.OnExit(e); + + Kernel.Dispose(); + } + + /// <summary> + /// Releases the mutex. + /// </summary> + private void ReleaseMutex() + { + if (SingleInstanceMutex == null) + { + return; + } + + SingleInstanceMutex.ReleaseMutex(); + SingleInstanceMutex.Close(); + SingleInstanceMutex.Dispose(); + SingleInstanceMutex = null; } /// <summary> @@ -179,21 +369,105 @@ namespace MediaBrowser.ServerApplication } /// <summary> - /// Instantiates the kernel. + /// Restarts this instance. + /// </summary> + /// <exception cref="System.NotImplementedException"></exception> + public void Restart() + { + Dispatcher.Invoke(ReleaseMutex); + + Kernel.Dispose(); + + System.Windows.Forms.Application.Restart(); + + Dispatcher.Invoke(Shutdown); + } + + /// <summary> + /// Reloads the logger. + /// </summary> + /// <exception cref="System.NotImplementedException"></exception> + public void ReloadLogger() + { + LogFilePath = Path.Combine(Kernel.ApplicationPaths.LogDirectoryPath, "Server-" + DateTime.Now.Ticks + ".log"); + + NlogManager.AddFileTarget(LogFilePath, Kernel.Configuration.EnableDebugLevelLogging); + } + + /// <summary> + /// Gets the image. + /// </summary> + /// <param name="uri">The URI.</param> + /// <returns>Image.</returns> + /// <exception cref="System.ArgumentNullException">uri</exception> + public Image GetImage(string uri) + { + if (string.IsNullOrEmpty(uri)) + { + throw new ArgumentNullException("uri"); + } + + return GetImage(new Uri(uri)); + } + + /// <summary> + /// Gets the image. + /// </summary> + /// <param name="uri">The URI.</param> + /// <returns>Image.</returns> + /// <exception cref="System.ArgumentNullException">uri</exception> + public Image GetImage(Uri uri) + { + if (uri == null) + { + throw new ArgumentNullException("uri"); + } + + return new Image { Source = GetBitmapImage(uri) }; + } + + /// <summary> + /// Gets the bitmap image. /// </summary> - /// <returns>IKernel.</returns> - protected override IKernel InstantiateKernel() + /// <param name="uri">The URI.</param> + /// <returns>BitmapImage.</returns> + /// <exception cref="System.ArgumentNullException">uri</exception> + public BitmapImage GetBitmapImage(string uri) { - return new Kernel(new PismoIsoManager(Logger), new DotNetZipClient(), new BdInfoExaminer(), Logger); + if (string.IsNullOrEmpty(uri)) + { + throw new ArgumentNullException("uri"); + } + + return GetBitmapImage(new Uri(uri)); } /// <summary> - /// Instantiates the main window. + /// Gets the bitmap image. /// </summary> - /// <returns>Window.</returns> - protected override Window InstantiateMainWindow() + /// <param name="uri">The URI.</param> + /// <returns>BitmapImage.</returns> + /// <exception cref="System.ArgumentNullException">uri</exception> + public BitmapImage GetBitmapImage(Uri uri) { - return new MainWindow(Logger); + if (uri == null) + { + throw new ArgumentNullException("uri"); + } + + var bitmap = new BitmapImage + { + CreateOptions = BitmapCreateOptions.DelayCreation, + CacheOption = BitmapCacheOption.OnDemand, + UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.CacheIfAvailable) + }; + + bitmap.BeginInit(); + bitmap.UriSource = uri; + bitmap.EndInit(); + + RenderOptions.SetBitmapScalingMode(bitmap, BitmapScalingMode.Fant); + return bitmap; } } } |
