using System.IO; using MediaBrowser.Common.Constants; using MediaBrowser.Common.Kernel; using MediaBrowser.Common.Updates; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations; using Microsoft.Win32; using System; using System.Diagnostics; 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 { /// /// Interaction logic for App.xaml /// public partial class App : Application { /// /// Defines the entry point of the application. /// [STAThread] public static void Main() { // Look for the existence of an update archive var appPaths = new ServerApplicationPaths(); var updateArchive = Path.Combine(appPaths.TempUpdatePath, Constants.MBServerPkgName + ".zip"); if (File.Exists(updateArchive)) { // Update is there - execute update try { new ApplicationUpdater().UpdateApplication(MBApplication.MBServer, appPaths, updateArchive); // And just let the app exit so it can update return; } catch (Exception e) { MessageBox.Show(string.Format("Error attempting to update application.\n\n{0}\n\n{1}", e.GetType().Name, e.Message)); } } var application = new App(); application.Run(); } /// /// Gets the instance. /// /// The instance. public static App Instance { get { return Current as App; } } /// /// The single instance mutex /// private Mutex SingleInstanceMutex; /// /// Gets or sets the kernel. /// /// The kernel. protected IKernel Kernel { get; set; } /// /// Gets or sets the logger. /// /// The logger. protected ILogger Logger { get; set; } /// /// Gets or sets the composition root. /// /// The composition root. protected ApplicationHost CompositionRoot { get; set; } /// /// Initializes a new instance of the class. /// /// The logger. public App() { InitializeComponent(); } /// /// Gets the name of the uninstaller file. /// /// The name of the uninstaller file. protected string UninstallerFileName { get { return "MediaBrowser.Server.Uninstall.exe"; } } /// /// Gets or sets a value indicating whether [last run at startup value]. /// /// null if [last run at startup value] contains no value, true if [last run at startup value]; otherwise, false. private bool? LastRunAtStartupValue { get; set; } /// /// Raises the event. /// /// A that contains the event data. protected override void OnStartup(StartupEventArgs e) { bool createdNew; SingleInstanceMutex = new Mutex(true, @"Local\" + GetType().Assembly.GetName().Name, out createdNew); if (!createdNew) { SingleInstanceMutex = null; Shutdown(); return; } AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; LoadKernel(); SystemEvents.SessionEnding += SystemEvents_SessionEnding; } /// /// Handles the UnhandledException event of the CurrentDomain control. /// /// The source of the event. /// The instance containing the event data. void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { var exception = (Exception)e.ExceptionObject; Logger.ErrorException("UnhandledException", exception); MessageBox.Show("Unhandled exception: " + exception.Message); } /// /// Handles the SessionEnding event of the SystemEvents control. /// /// The source of the event. /// The instance containing the event data. void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) { // Try to shut down gracefully Shutdown(); } /// /// Loads the kernel. /// protected async void LoadKernel() { CompositionRoot = new ApplicationHost(); Logger = CompositionRoot.Logger; Kernel = CompositionRoot.Kernel; try { var win = (MainWindow)CompositionRoot.CreateInstance(typeof(MainWindow)); win.Show(); var now = DateTime.UtcNow; 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); } } /// /// Called when [kernel loaded]. /// /// Task. protected Task OnKernelLoaded() { return Task.Run(() => { Kernel.ConfigurationUpdated += Kernel_ConfigurationUpdated; ConfigureAutoRun(); }); } /// /// Handles the ConfigurationUpdated event of the Kernel control. /// /// The source of the event. /// The instance containing the event data. void Kernel_ConfigurationUpdated(object sender, EventArgs e) { if (!LastRunAtStartupValue.HasValue || LastRunAtStartupValue.Value != Kernel.Configuration.RunAtStartup) { ConfigureAutoRun(); } } /// /// Configures the click once startup. /// private void ConfigureAutoRun() { CompositionRoot.ConfigureAutoRunAtStartup(Kernel.Configuration.RunAtStartup); } /// /// Raises the event. /// /// An that contains the event data. protected override void OnExit(ExitEventArgs e) { ReleaseMutex(); base.OnExit(e); CompositionRoot.Dispose(); } /// /// Releases the mutex. /// private void ReleaseMutex() { if (SingleInstanceMutex == null) { return; } SingleInstanceMutex.ReleaseMutex(); SingleInstanceMutex.Close(); SingleInstanceMutex.Dispose(); SingleInstanceMutex = null; } /// /// Opens the dashboard. /// public static void OpenDashboard(User loggedInUser) { OpenDashboardPage("dashboard.html", loggedInUser); } /// /// Opens the dashboard page. /// /// The page. public static void OpenDashboardPage(string page, User loggedInUser) { var url = "http://localhost:" + Controller.Kernel.Instance.Configuration.HttpServerPortNumber + "/" + Controller.Kernel.Instance.WebApplicationName + "/dashboard/" + page; if (loggedInUser != null) { url = AddAutoLoginToDashboardUrl(url, loggedInUser); } OpenUrl(url); } /// /// Adds the auto login to dashboard URL. /// /// The URL. /// The user. /// System.String. public static string AddAutoLoginToDashboardUrl(string url, User user) { if (url.IndexOf('?') == -1) { url += "?u=" + user.Id; } else { url += "&u=" + user.Id; } return url; } /// /// Opens the URL. /// /// The URL. public static void OpenUrl(string url) { var process = new Process { StartInfo = new ProcessStartInfo { FileName = url }, EnableRaisingEvents = true }; process.Exited += ProcessExited; process.Start(); } /// /// Processes the exited. /// /// The sender. /// The instance containing the event data. static void ProcessExited(object sender, EventArgs e) { ((Process)sender).Dispose(); } /// /// Restarts this instance. /// /// public void Restart() { Dispatcher.Invoke(ReleaseMutex); CompositionRoot.Dispose(); System.Windows.Forms.Application.Restart(); Dispatcher.Invoke(Shutdown); } /// /// Gets the image. /// /// The URI. /// Image. /// uri public Image GetImage(string uri) { if (string.IsNullOrEmpty(uri)) { throw new ArgumentNullException("uri"); } return GetImage(new Uri(uri)); } /// /// Gets the image. /// /// The URI. /// Image. /// uri public Image GetImage(Uri uri) { if (uri == null) { throw new ArgumentNullException("uri"); } return new Image { Source = GetBitmapImage(uri) }; } /// /// Gets the bitmap image. /// /// The URI. /// BitmapImage. /// uri public BitmapImage GetBitmapImage(string uri) { if (string.IsNullOrEmpty(uri)) { throw new ArgumentNullException("uri"); } return GetBitmapImage(new Uri(uri)); } /// /// Gets the bitmap image. /// /// The URI. /// BitmapImage. /// uri public BitmapImage GetBitmapImage(Uri uri) { 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; } } }