starting point towards running as a service
This commit is contained in:
parent
e50c29ffca
commit
f3ce127a62
|
@ -133,8 +133,8 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await Task.Delay(100);
|
await Task.Delay(100).ConfigureAwait(false);
|
||||||
_appHost.Restart();
|
await _appHost.Restart().ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,8 +146,8 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await Task.Delay(100);
|
await Task.Delay(100).ConfigureAwait(false);
|
||||||
_appHost.Shutdown();
|
await _appHost.Shutdown().ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -552,7 +552,7 @@ namespace MediaBrowser.Common.Implementations
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restarts this instance.
|
/// Restarts this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void Restart();
|
public abstract Task Restart();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance can self update.
|
/// Gets or sets a value indicating whether this instance can self update.
|
||||||
|
@ -582,7 +582,7 @@ namespace MediaBrowser.Common.Implementations
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shuts down.
|
/// Shuts down.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract void Shutdown();
|
public abstract Task Shutdown();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when [application updated].
|
/// Called when [application updated].
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace MediaBrowser.Common
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restarts this instance.
|
/// Restarts this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Restart();
|
Task Restart();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the application version.
|
/// Gets the application version.
|
||||||
|
@ -113,7 +113,7 @@ namespace MediaBrowser.Common
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shuts down.
|
/// Shuts down.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Shutdown();
|
Task Shutdown();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugins.
|
/// Gets the plugins.
|
||||||
|
|
|
@ -25,5 +25,11 @@ namespace MediaBrowser.Controller
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The HTTP server URL prefix.</value>
|
/// <value>The HTTP server URL prefix.</value>
|
||||||
string HttpServerUrlPrefix { get; }
|
string HttpServerUrlPrefix { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this instance is background service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is background service; otherwise, <c>false</c>.</value>
|
||||||
|
bool IsBackgroundService { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,13 @@ namespace MediaBrowser.Model.System
|
||||||
public int HttpServerPortNumber { get; set; }
|
public int HttpServerPortNumber { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SystemInfo"/> class.
|
/// Gets or sets a value indicating whether this instance is background service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is background service; otherwise, <c>false</c>.</value>
|
||||||
|
public bool IsBackgroundService { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="SystemInfo" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SystemInfo()
|
public SystemInfo()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,89 +1,19 @@
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Common.Constants;
|
|
||||||
using MediaBrowser.Common.Implementations.Updates;
|
|
||||||
using MediaBrowser.Controller;
|
|
||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Server.Implementations;
|
|
||||||
using MediaBrowser.ServerApplication.Splash;
|
using MediaBrowser.ServerApplication.Splash;
|
||||||
using Microsoft.Win32;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
using System.Net.Cache;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
|
|
||||||
namespace MediaBrowser.ServerApplication
|
namespace MediaBrowser.ServerApplication
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for App.xaml
|
/// Interaction logic for App.xaml
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class App : Application
|
public partial class App : Application, IApplicationInterface
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The single instance mutex
|
|
||||||
/// </summary>
|
|
||||||
private static Mutex _singleInstanceMutex;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the entry point of the application.
|
|
||||||
/// </summary>
|
|
||||||
[STAThread]
|
|
||||||
public static void Main()
|
|
||||||
{
|
|
||||||
bool createdNew;
|
|
||||||
|
|
||||||
var runningPath = Process.GetCurrentProcess().MainModule.FileName.Replace(Path.DirectorySeparatorChar.ToString(), string.Empty);
|
|
||||||
|
|
||||||
_singleInstanceMutex = new Mutex(true, @"Local\" + runningPath, out createdNew);
|
|
||||||
|
|
||||||
if (!createdNew)
|
|
||||||
{
|
|
||||||
_singleInstanceMutex = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The instance.</value>
|
|
||||||
public static App Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return Current as App;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the logger.
|
/// Gets or sets the logger.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -95,7 +25,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The composition root.</value>
|
/// <value>The composition root.</value>
|
||||||
protected ApplicationHost CompositionRoot { get; set; }
|
protected ApplicationHost CompositionRoot { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="App" /> class.
|
/// Initializes a new instance of the <see cref="App" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -105,6 +35,11 @@ namespace MediaBrowser.ServerApplication
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsBackgroundService
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name of the uninstaller file.
|
/// Gets the name of the uninstaller file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -114,63 +49,35 @@ namespace MediaBrowser.ServerApplication
|
||||||
get { return "MediaBrowser.Server.Uninstall.exe"; }
|
get { return "MediaBrowser.Server.Uninstall.exe"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void OnUnhandledException(Exception ex)
|
||||||
/// Raises the <see cref="E:System.Windows.Application.Startup" /> event.
|
{
|
||||||
/// </summary>
|
Logger.ErrorException("UnhandledException", ex);
|
||||||
/// <param name="e">A <see cref="T:System.Windows.StartupEventArgs" /> that contains the event data.</param>
|
|
||||||
|
MessageBox.Show("Unhandled exception: " + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnStartup(StartupEventArgs e)
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
{
|
{
|
||||||
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
base.OnStartup(e);
|
||||||
LoadKernel();
|
|
||||||
|
|
||||||
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
|
LoadApplication();
|
||||||
}
|
|
||||||
|
|
||||||
/// <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);
|
|
||||||
|
|
||||||
if (!Debugger.IsAttached)
|
|
||||||
{
|
|
||||||
Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(exception));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <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>
|
/// <summary>
|
||||||
/// Loads the kernel.
|
/// Loads the kernel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected async void LoadKernel()
|
protected async void LoadApplication()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CompositionRoot = new ApplicationHost();
|
CompositionRoot = new ApplicationHost(this);
|
||||||
|
|
||||||
Logger = CompositionRoot.LogManager.GetLogger("App");
|
Logger = CompositionRoot.LogManager.GetLogger("App");
|
||||||
|
|
||||||
var splash = new SplashWindow(CompositionRoot.ApplicationVersion);
|
var splash = new SplashWindow(CompositionRoot.ApplicationVersion);
|
||||||
|
|
||||||
splash.Show();
|
splash.Show();
|
||||||
|
|
||||||
await CompositionRoot.Init();
|
await CompositionRoot.Init();
|
||||||
|
|
||||||
splash.Hide();
|
splash.Hide();
|
||||||
|
@ -192,13 +99,18 @@ namespace MediaBrowser.ServerApplication
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ShutdownApplication()
|
||||||
|
{
|
||||||
|
Dispatcher.Invoke(Shutdown);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raises the <see cref="E:System.Windows.Application.Exit" /> event.
|
/// Raises the <see cref="E:System.Windows.Application.Exit" /> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="e">An <see cref="T:System.Windows.ExitEventArgs" /> that contains the event data.</param>
|
/// <param name="e">An <see cref="T:System.Windows.ExitEventArgs" /> that contains the event data.</param>
|
||||||
protected override void OnExit(ExitEventArgs e)
|
protected override void OnExit(ExitEventArgs e)
|
||||||
{
|
{
|
||||||
ReleaseMutex();
|
MainStartup.ReleaseMutex();
|
||||||
|
|
||||||
base.OnExit(e);
|
base.OnExit(e);
|
||||||
|
|
||||||
|
@ -208,22 +120,6 @@ namespace MediaBrowser.ServerApplication
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Releases the mutex.
|
|
||||||
/// </summary>
|
|
||||||
private void ReleaseMutex()
|
|
||||||
{
|
|
||||||
if (_singleInstanceMutex == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_singleInstanceMutex.ReleaseMutex();
|
|
||||||
_singleInstanceMutex.Close();
|
|
||||||
_singleInstanceMutex.Dispose();
|
|
||||||
_singleInstanceMutex = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the dashboard page.
|
/// Opens the dashboard page.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -281,9 +177,9 @@ namespace MediaBrowser.ServerApplication
|
||||||
/// Restarts this instance.
|
/// Restarts this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <exception cref="System.NotImplementedException"></exception>
|
/// <exception cref="System.NotImplementedException"></exception>
|
||||||
public void Restart()
|
public void RestartApplication()
|
||||||
{
|
{
|
||||||
Dispatcher.Invoke(ReleaseMutex);
|
Dispatcher.Invoke(MainStartup.ReleaseMutex);
|
||||||
|
|
||||||
CompositionRoot.Dispose();
|
CompositionRoot.Dispose();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Windows.Forms;
|
using MediaBrowser.Api;
|
||||||
using MediaBrowser.Api;
|
|
||||||
using MediaBrowser.Common;
|
using MediaBrowser.Common;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Constants;
|
using MediaBrowser.Common.Constants;
|
||||||
|
@ -7,7 +6,6 @@ using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Implementations;
|
using MediaBrowser.Common.Implementations;
|
||||||
using MediaBrowser.Common.Implementations.IO;
|
using MediaBrowser.Common.Implementations.IO;
|
||||||
using MediaBrowser.Common.Implementations.ScheduledTasks;
|
using MediaBrowser.Common.Implementations.ScheduledTasks;
|
||||||
using MediaBrowser.Common.Implementations.Updates;
|
|
||||||
using MediaBrowser.Common.MediaInfo;
|
using MediaBrowser.Common.MediaInfo;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
|
@ -184,6 +182,13 @@ namespace MediaBrowser.ServerApplication
|
||||||
private IItemRepository ItemRepository { get; set; }
|
private IItemRepository ItemRepository { get; set; }
|
||||||
private INotificationsRepository NotificationsRepository { get; set; }
|
private INotificationsRepository NotificationsRepository { get; set; }
|
||||||
|
|
||||||
|
public bool IsBackgroundService
|
||||||
|
{
|
||||||
|
get { return _appInterface != null && _appInterface.IsBackgroundService; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IApplicationInterface _appInterface;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The full path to our startmenu shortcut
|
/// The full path to our startmenu shortcut
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -194,6 +199,11 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
private Task<IHttpServer> _httpServerCreationTask;
|
private Task<IHttpServer> _httpServerCreationTask;
|
||||||
|
|
||||||
|
public ApplicationHost(IApplicationInterface appInterface)
|
||||||
|
{
|
||||||
|
_appInterface = appInterface;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs the startup tasks.
|
/// Runs the startup tasks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -505,7 +515,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
base.OnConfigurationUpdated(sender, e);
|
base.OnConfigurationUpdated(sender, e);
|
||||||
|
|
||||||
HttpServer.EnableHttpRequestLogging = ServerConfigurationManager.Configuration.EnableHttpLevelLogging;
|
HttpServer.EnableHttpRequestLogging = ServerConfigurationManager.Configuration.EnableHttpLevelLogging;
|
||||||
|
|
||||||
if (!string.Equals(HttpServer.UrlPrefix, HttpServerUrlPrefix, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(HttpServer.UrlPrefix, HttpServerUrlPrefix, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
NotifyPendingRestart();
|
NotifyPendingRestart();
|
||||||
|
@ -521,19 +531,18 @@ namespace MediaBrowser.ServerApplication
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Restarts this instance.
|
/// Restarts this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override void Restart()
|
public override async Task Restart()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var task = ServerManager.SendWebSocketMessageAsync("ServerRestarting", () => string.Empty, CancellationToken.None);
|
await ServerManager.SendWebSocketMessageAsync("ServerRestarting", () => string.Empty, CancellationToken.None).ConfigureAwait(false);
|
||||||
task.Wait();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.ErrorException("Error sending server restart web socket message", ex);
|
Logger.ErrorException("Error sending server restart web socket message", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
App.Instance.Restart();
|
_appInterface.RestartApplication();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -618,7 +627,8 @@ namespace MediaBrowser.ServerApplication
|
||||||
Id = _systemId,
|
Id = _systemId,
|
||||||
ProgramDataPath = ApplicationPaths.ProgramDataPath,
|
ProgramDataPath = ApplicationPaths.ProgramDataPath,
|
||||||
MacAddress = GetMacAddress(),
|
MacAddress = GetMacAddress(),
|
||||||
HttpServerPortNumber = ServerConfigurationManager.Configuration.HttpServerPortNumber
|
HttpServerPortNumber = ServerConfigurationManager.Configuration.HttpServerPortNumber,
|
||||||
|
IsBackgroundService = IsBackgroundService
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,19 +652,18 @@ namespace MediaBrowser.ServerApplication
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shuts down.
|
/// Shuts down.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override void Shutdown()
|
public override async Task Shutdown()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var task = ServerManager.SendWebSocketMessageAsync("ServerShuttingDown", () => string.Empty, CancellationToken.None);
|
await ServerManager.SendWebSocketMessageAsync("ServerShuttingDown", () => string.Empty, CancellationToken.None).ConfigureAwait(false);
|
||||||
task.Wait();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.ErrorException("Error sending server shutdown web socket message", ex);
|
Logger.ErrorException("Error sending server shutdown web socket message", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
App.Instance.Dispatcher.Invoke(App.Instance.Shutdown);
|
_appInterface.ShutdownApplication();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
30
MediaBrowser.ServerApplication/BackgroundService.cs
Normal file
30
MediaBrowser.ServerApplication/BackgroundService.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System.ServiceProcess;
|
||||||
|
|
||||||
|
namespace MediaBrowser.ServerApplication
|
||||||
|
{
|
||||||
|
public class BackgroundService : ServiceBase
|
||||||
|
{
|
||||||
|
public BackgroundService()
|
||||||
|
{
|
||||||
|
CanPauseAndContinue = false;
|
||||||
|
CanHandleSessionChangeEvent = true;
|
||||||
|
CanStop = false;
|
||||||
|
CanShutdown = true;
|
||||||
|
ServiceName = "Media Browser";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnSessionChange(SessionChangeDescription changeDescription)
|
||||||
|
{
|
||||||
|
base.OnSessionChange(changeDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnStart(string[] args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnShutdown()
|
||||||
|
{
|
||||||
|
base.OnShutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,7 +64,10 @@ namespace MediaBrowser.ServerApplication.EntryPoints
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error launching startup wizard", ex);
|
_logger.ErrorException("Error launching startup wizard", ex);
|
||||||
|
|
||||||
MessageBox.Show("There was an error launching the Media Browser startup wizard. Please ensure a web browser is installed on the machine and is configured as the default browser.", "Media Browser");
|
if (!_appHost.IsBackgroundService)
|
||||||
|
{
|
||||||
|
MessageBox.Show("There was an error launching the Media Browser startup wizard. Please ensure a web browser is installed on the machine and is configured as the default browser.", "Media Browser");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
MediaBrowser.ServerApplication/IApplicationInterface.cs
Normal file
32
MediaBrowser.ServerApplication/IApplicationInterface.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MediaBrowser.ServerApplication
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface IApplicationInterface
|
||||||
|
/// </summary>
|
||||||
|
public interface IApplicationInterface
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this instance is background service.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if this instance is background service; otherwise, <c>false</c>.</value>
|
||||||
|
bool IsBackgroundService { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shutdowns the application.
|
||||||
|
/// </summary>
|
||||||
|
void ShutdownApplication();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restarts the application.
|
||||||
|
/// </summary>
|
||||||
|
void RestartApplication();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when [unhandled exception].
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ex">The ex.</param>
|
||||||
|
void OnUnhandledException(Exception ex);
|
||||||
|
}
|
||||||
|
}
|
134
MediaBrowser.ServerApplication/MainStartup.cs
Normal file
134
MediaBrowser.ServerApplication/MainStartup.cs
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
using MediaBrowser.Common.Constants;
|
||||||
|
using MediaBrowser.Common.Implementations.Updates;
|
||||||
|
using MediaBrowser.Server.Implementations;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
namespace MediaBrowser.ServerApplication
|
||||||
|
{
|
||||||
|
public class MainStartup
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The single instance mutex
|
||||||
|
/// </summary>
|
||||||
|
private static Mutex _singleInstanceMutex;
|
||||||
|
|
||||||
|
private static IApplicationInterface _applicationInterface;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the entry point of the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
|
||||||
|
|
||||||
|
bool createdNew;
|
||||||
|
|
||||||
|
var runningPath = Process.GetCurrentProcess().MainModule.FileName.Replace(Path.DirectorySeparatorChar.ToString(), string.Empty);
|
||||||
|
|
||||||
|
_singleInstanceMutex = new Mutex(true, @"Local\" + runningPath, out createdNew);
|
||||||
|
|
||||||
|
if (!createdNew)
|
||||||
|
{
|
||||||
|
_singleInstanceMutex = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StartApplication();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StartApplication()
|
||||||
|
{
|
||||||
|
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
|
||||||
|
var commandLineArgs = Environment.GetCommandLineArgs();
|
||||||
|
|
||||||
|
if (commandLineArgs.Length > 1 && commandLineArgs[1].Equals("-service"))
|
||||||
|
{
|
||||||
|
// Start application as a service
|
||||||
|
StartBackgroundService();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StartWpfApp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
|
||||||
|
{
|
||||||
|
// Try to shutdown gracefully
|
||||||
|
if (_applicationInterface != null)
|
||||||
|
{
|
||||||
|
_applicationInterface.ShutdownApplication();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StartWpfApp()
|
||||||
|
{
|
||||||
|
var app = new App();
|
||||||
|
|
||||||
|
_applicationInterface = app;
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StartBackgroundService()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
|
{
|
||||||
|
var exception = (Exception)e.ExceptionObject;
|
||||||
|
|
||||||
|
if (_applicationInterface != null)
|
||||||
|
{
|
||||||
|
_applicationInterface.OnUnhandledException(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Debugger.IsAttached)
|
||||||
|
{
|
||||||
|
Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(exception));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the mutex.
|
||||||
|
/// </summary>
|
||||||
|
internal static void ReleaseMutex()
|
||||||
|
{
|
||||||
|
if (_singleInstanceMutex == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_singleInstanceMutex.ReleaseMutex();
|
||||||
|
_singleInstanceMutex.Close();
|
||||||
|
_singleInstanceMutex.Dispose();
|
||||||
|
_singleInstanceMutex = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -119,7 +119,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
Dispatcher.InvokeAsync(() =>
|
Dispatcher.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
var logWindow = App.Instance.Windows.OfType<LogWindow>().FirstOrDefault();
|
var logWindow = App.Current.Windows.OfType<LogWindow>().FirstOrDefault();
|
||||||
|
|
||||||
if ((logWindow == null && _configurationManager.Configuration.ShowLogWindow) || (logWindow != null && !_configurationManager.Configuration.ShowLogWindow))
|
if ((logWindow == null && _configurationManager.Configuration.ShowLogWindow) || (logWindow != null && !_configurationManager.Configuration.ShowLogWindow))
|
||||||
{
|
{
|
||||||
|
@ -204,7 +204,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
{
|
{
|
||||||
App.OpenUrl("https://github.com/MediaBrowser/MediaBrowser/wiki");
|
App.OpenUrl("https://github.com/MediaBrowser/MediaBrowser/wiki");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when [property changed].
|
/// Occurs when [property changed].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -258,7 +258,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
{
|
{
|
||||||
App.OpenDashboardPage("dashboard.html", loggedInUser, _configurationManager, _appHost);
|
App.OpenDashboardPage("dashboard.html", loggedInUser, _configurationManager, _appHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles the click event of the cmVisitCT control.
|
/// Handles the click event of the cmVisitCT control.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -285,9 +285,9 @@ namespace MediaBrowser.ServerApplication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The source of the event.</param>
|
/// <param name="sender">The source of the event.</param>
|
||||||
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
|
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
|
||||||
private void cmExit_click(object sender, RoutedEventArgs e)
|
private async void cmExit_click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Application.Current.Shutdown();
|
await _appHost.Shutdown().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -295,9 +295,9 @@ namespace MediaBrowser.ServerApplication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The source of the event.</param>
|
/// <param name="sender">The source of the event.</param>
|
||||||
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
|
/// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
|
||||||
private void cmdReloadServer_click(object sender, RoutedEventArgs e)
|
private async void cmdReloadServer_click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
App.Instance.Restart();
|
await _appHost.Restart().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<StartupObject>MediaBrowser.ServerApplication.App</StartupObject>
|
<StartupObject>MediaBrowser.ServerApplication.MainStartup</StartupObject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ApplicationIcon>Resources\Images\icon.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\Images\icon.ico</ApplicationIcon>
|
||||||
|
@ -187,6 +187,7 @@
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Net.Http.WebRequest" />
|
<Reference Include="System.Net.Http.WebRequest" />
|
||||||
<Reference Include="System.Runtime.Remoting" />
|
<Reference Include="System.Runtime.Remoting" />
|
||||||
|
<Reference Include="System.ServiceProcess" />
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\MahApps.Metro.0.11.0.17-ALPHA\lib\net45\System.Windows.Interactivity.dll</HintPath>
|
<HintPath>..\packages\MahApps.Metro.0.11.0.17-ALPHA\lib\net45\System.Windows.Interactivity.dll</HintPath>
|
||||||
|
@ -203,8 +204,13 @@
|
||||||
<Reference Include="PresentationFramework" />
|
<Reference Include="PresentationFramework" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="BackgroundService.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
<Compile Include="EntryPoints\StartupWizard.cs" />
|
<Compile Include="EntryPoints\StartupWizard.cs" />
|
||||||
<Compile Include="EntryPoints\UdpServerEntryPoint.cs" />
|
<Compile Include="EntryPoints\UdpServerEntryPoint.cs" />
|
||||||
|
<Compile Include="IApplicationInterface.cs" />
|
||||||
|
<Compile Include="MainStartup.cs" />
|
||||||
<Compile Include="Splash\SplashWindow.xaml.cs">
|
<Compile Include="Splash\SplashWindow.xaml.cs">
|
||||||
<DependentUpon>SplashWindow.xaml</DependentUpon>
|
<DependentUpon>SplashWindow.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user