update .net core startup

This commit is contained in:
Luke Pulverenti
2016-11-12 23:33:51 -05:00
parent 3e06bda46b
commit 95341c5c96
20 changed files with 602 additions and 632 deletions

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Emby.Server
{
public class ApplicationPathHelper
{
public static string GetProgramDataPath(string applicationPath)
{
var useDebugPath = false;
#if DEBUG
useDebugPath = true;
#endif
var programDataPath = useDebugPath ?
"programdata" :
"programdata";
programDataPath = programDataPath
.Replace('/', Path.DirectorySeparatorChar)
.Replace('\\', Path.DirectorySeparatorChar);
// If it's a relative path, e.g. "..\"
if (!Path.IsPathRooted(programDataPath))
{
var path = Path.GetDirectoryName(applicationPath);
if (string.IsNullOrEmpty(path))
{
throw new Exception("Unable to determine running assembly location");
}
programDataPath = Path.Combine(path, programDataPath);
programDataPath = Path.GetFullPath(programDataPath);
}
Directory.CreateDirectory(programDataPath);
return programDataPath;
}
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Emby.Server.Core;
using Emby.Server.Core.Data;
using Emby.Server.Core.FFMpeg;
using Emby.Server.Data;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.System;
namespace Emby.Server
{
public class CoreAppHost : ApplicationHost
{
public CoreAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action<string, string> certificateGenerator, Func<string> defaultUsernameFactory)
: base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory)
{
}
public override bool IsRunningAsService
{
get { return false; }
}
protected override void RestartInternal()
{
Program.Restart();
}
protected override void ShutdownInternal()
{
Program.Shutdown();
}
protected override FFMpegInstallInfo GetFfmpegInstallInfo()
{
var info = new FFMpegInstallInfo();
return info;
}
protected override List<Assembly> GetAssembliesWithPartsInternal()
{
var list = new List<Assembly>();
list.Add(GetType().GetTypeInfo().Assembly);
return list;
}
protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory)
{
}
protected override IDbConnector GetDbConnector()
{
return new DbConnector(Logger);
}
protected override void ConfigureAutoRunInternal(bool autorun)
{
}
public override void LaunchUrl(string url)
{
}
protected override void EnableLoopbackInternal(string appName)
{
}
public override bool SupportsRunningAsService
{
get
{
return true;
}
}
public override bool CanSelfRestart
{
get
{
return Program.CanSelfRestart;
}
}
public override bool SupportsAutoRunAtStartup
{
get
{
return true;
}
}
public override bool CanSelfUpdate
{
get
{
return Program.CanSelfUpdate;
}
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
using MediaBrowser.Model.System;
namespace Emby.Server
{
public class CoreSystemEvents : ISystemEvents
{
public event EventHandler Resume;
public event EventHandler Suspend;
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Data;
using System.Threading.Tasks;
using MediaBrowser.Model.Logging;
using Emby.Server.Core.Data;
using Microsoft.Data.Sqlite;
namespace Emby.Server.Data
{
public class DbConnector : IDbConnector
{
private readonly ILogger _logger;
public DbConnector(ILogger logger)
{
_logger = logger;
}
public async Task<IDbConnection> Connect(string dbPath, bool isReadOnly, bool enablePooling = false, int? cacheSize = null)
{
if (string.IsNullOrEmpty(dbPath))
{
throw new ArgumentNullException("dbPath");
}
//SQLiteConnection.SetMemoryStatus(false);
var connectionstr = new SqliteConnectionStringBuilder
{
//PageSize = 4096,
//CacheSize = cacheSize ?? 2000,
//SyncMode = SynchronizationModes.Normal,
DataSource = dbPath,
//JournalMode = SQLiteJournalModeEnum.Wal,
// This is causing crashing under linux
//Pooling = enablePooling && Environment.OSVersion.Platform == PlatformID.Win32NT,
//ReadOnly = isReadOnly,
Cache = enablePooling ? SqliteCacheMode.Default : SqliteCacheMode.Private,
Mode = isReadOnly ? SqliteOpenMode.ReadOnly : SqliteOpenMode.ReadWriteCreate
};
var connectionString = connectionstr.ConnectionString;
var connection = new SqliteConnection(connectionString);
await connection.OpenAsync().ConfigureAwait(false);
return connection;
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.IO;
using MediaBrowser.Model.IO;
namespace Emby.Server.IO
{
public class MemoryStreamFactory : IMemoryStreamFactory
{
public MemoryStream CreateNew()
{
return new MemoryStream();
}
public MemoryStream CreateNew(int capacity)
{
return new MemoryStream(capacity);
}
public MemoryStream CreateNew(byte[] buffer)
{
return new MemoryStream(buffer);
}
public bool TryGetBuffer(MemoryStream stream, out byte[] buffer)
{
ArraySegment<byte> arrayBuffer;
stream.TryGetBuffer(out arrayBuffer);
buffer = arrayBuffer.Array;
return true;
}
}
}

View File

@@ -0,0 +1,15 @@
using MediaBrowser.Model.System;
namespace Emby.Server
{
public class PowerManagement : IPowerManagement
{
public void PreventSystemStandby()
{
}
public void AllowSystemStandby()
{
}
}
}

View File

@@ -1,33 +1,24 @@
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations;
using MediaBrowser.Server.Startup.Common;
using MediaBrowser.ServerApplication.Native;
using MediaBrowser.ServerApplication.Splash;
using MediaBrowser.ServerApplication.Updates;
using Microsoft.Win32;
using System;
using System.Configuration.Install;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emby.Common.Implementations.EnvironmentInfo;
using Emby.Common.Implementations.IO;
using Emby.Common.Implementations.Logging;
using Emby.Common.Implementations.Networking;
using Emby.Common.Implementations.Security;
using Emby.Drawing;
using Emby.Server.Core;
using Emby.Server.Core.Browser;
using Emby.Server.Implementations.IO;
using ImageMagickSharp;
using MediaBrowser.Common.Net;
using MediaBrowser.Server.Startup.Common.IO;
using Emby.Server.IO;
namespace Emby.Server
{
@@ -60,11 +51,11 @@ namespace Emby.Server
var currentProcess = Process.GetCurrentProcess();
var applicationPath = currentProcess.MainModule.FileName;
var architecturePath = Path.Combine(Path.GetDirectoryName(applicationPath), Environment.Is64BitProcess ? "x64" : "x86");
//var architecturePath = Path.Combine(Path.GetDirectoryName(applicationPath), Environment.Is64BitProcess ? "x64" : "x86");
Wand.SetMagickCoderModulePath(architecturePath);
//Wand.SetMagickCoderModulePath(architecturePath);
var success = SetDllDirectory(architecturePath);
//var success = SetDllDirectory(architecturePath);
var appPaths = CreateApplicationPaths(applicationPath, _isRunningAsService);
@@ -227,31 +218,25 @@ namespace Emby.Server
/// <param name="options">The options.</param>
private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, bool runService, StartupOptions options)
{
var fileSystem = new WindowsFileSystem(logManager.GetLogger("FileSystem"));
fileSystem.AddShortcutHandler(new LnkShortcutHandler());
var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), true, true, true);
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
var nativeApp = new WindowsApp(fileSystem, _logger)
{
IsRunningAsService = runService
};
var imageEncoder = new NullImageEncoder();
var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths);
_appHost = new ApplicationHost(appPaths,
_appHost = new CoreAppHost(appPaths,
logManager,
options,
fileSystem,
nativeApp,
new PowerManagement(),
"emby.windows.zip",
new EnvironmentInfo(),
imageEncoder,
new Server.Startup.Common.SystemEvents(logManager.GetLogger("SystemEvents")),
new RecyclableMemoryStreamProvider(),
new CoreSystemEvents(),
new MemoryStreamFactory(),
new NetworkManager(logManager.GetLogger("NetworkManager")),
GenerateCertificate,
() => Environment.UserDomainName);
() => "EmbyUser");
var initProgress = new Progress<double>();
@@ -275,12 +260,6 @@ namespace Emby.Server
{
Task.WaitAll(task);
task = InstallVcredist2013IfNeeded(_appHost, _logger);
Task.WaitAll(task);
Microsoft.Win32.SystemEvents.SessionEnding += SystemEvents_SessionEnding;
Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
task = ApplicationTaskCompletionSource.Task;
Task.WaitAll(task);
}
@@ -288,15 +267,7 @@ namespace Emby.Server
private static void GenerateCertificate(string certPath, string certHost)
{
CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger);
}
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionLogon)
{
BrowserLauncher.OpenDashboard(_appHost);
}
//CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger);
}
/// <summary>
@@ -304,11 +275,6 @@ namespace Emby.Server
/// </summary>
private static void StartService(ILogManager logManager)
{
var service = new BackgroundService(logManager.GetLogger("Service"));
service.Disposed += service_Disposed;
ServiceBase.Run(service);
}
/// <summary>
@@ -329,19 +295,6 @@ namespace Emby.Server
DisposeAppHost();
}
/// <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>
static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
if (e.Reason == SessionEndReasons.SystemShutdown || !_isRunningAsService)
{
Shutdown();
}
}
/// <summary>
/// Handles the UnhandledException event of the CurrentDomain control.
/// </summary>
@@ -355,7 +308,7 @@ namespace Emby.Server
if (!_isRunningAsService)
{
MessageBox.Show("Unhandled exception: " + exception.Message);
ShowMessageBox("Unhandled exception: " + exception.Message);
}
if (!Debugger.IsAttached)
@@ -381,8 +334,8 @@ namespace Emby.Server
// Update is there - execute update
try
{
var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty;
new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName);
//var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty;
//new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName);
// And just let the app exit so it can update
return true;
@@ -391,13 +344,18 @@ namespace Emby.Server
{
logger.ErrorException("Error starting updater.", e);
MessageBox.Show(string.Format("Error attempting to update application.\n\n{0}\n\n{1}", e.GetType().Name, e.Message));
ShowMessageBox(string.Format("Error attempting to update application.\n\n{0}\n\n{1}", e.GetType().Name, e.Message));
}
}
return false;
}
private static void ShowMessageBox(string msg)
{
}
public static void Shutdown()
{
if (_isRunningAsService)
@@ -469,90 +427,6 @@ namespace Emby.Server
return false;
}
private static async Task InstallVcredist2013IfNeeded(ApplicationHost appHost, ILogger logger)
{
// Reference
// http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed
try
{
var subkey = Environment.Is64BitProcess
? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x64"
: "SOFTWARE\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x86";
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)
.OpenSubKey(subkey))
{
if (ndpKey != null && ndpKey.GetValue("Version") != null)
{
var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v');
if (installedVersion.StartsWith("12", StringComparison.OrdinalIgnoreCase))
{
return;
}
}
}
}
catch (Exception ex)
{
logger.ErrorException("Error getting .NET Framework version", ex);
return;
}
try
{
await InstallVcredist2013().ConfigureAwait(false);
}
catch (Exception ex)
{
logger.ErrorException("Error installing Visual Studio C++ runtime", ex);
}
}
private async static Task InstallVcredist2013()
{
var httpClient = _appHost.HttpClient;
var tmp = await httpClient.GetTempFile(new HttpRequestOptions
{
Url = GetVcredist2013Url(),
Progress = new Progress<double>()
}).ConfigureAwait(false);
var exePath = Path.ChangeExtension(tmp, ".exe");
File.Copy(tmp, exePath);
var startInfo = new ProcessStartInfo
{
FileName = exePath,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
Verb = "runas",
ErrorDialog = false
};
_logger.Info("Running {0}", startInfo.FileName);
using (var process = Process.Start(startInfo))
{
process.WaitForExit();
}
}
private static string GetVcredist2013Url()
{
if (Environment.Is64BitProcess)
{
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe";
}
// TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe
return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe";
}
/// <summary>
/// Sets the error mode.
/// </summary>

View File

@@ -11,7 +11,11 @@
"type": "platform",
"version": "1.0.1"
},
"Mono.Nat": "1.0.0-*"
"Mono.Nat": "1.0.0-*",
"Microsoft.Win32.Registry": "4.0.0",
"System.Runtime.Extensions": "4.1.0",
"System.Diagnostics.Process": "4.1.0",
"Microsoft.Data.SQLite": "1.0.0"
},
"frameworks": {