update .net core startup
This commit is contained in:
parent
3e06bda46b
commit
95341c5c96
|
@ -18,12 +18,13 @@ namespace Emby.Common.Implementations.IO
|
||||||
private readonly bool _supportsAsyncFileStreams;
|
private readonly bool _supportsAsyncFileStreams;
|
||||||
private char[] _invalidFileNameChars;
|
private char[] _invalidFileNameChars;
|
||||||
private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
|
private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
|
||||||
protected bool EnableFileSystemRequestConcat = true;
|
private bool EnableFileSystemRequestConcat = true;
|
||||||
|
|
||||||
public ManagedFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars)
|
public ManagedFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars, bool enableFileSystemRequestConcat)
|
||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
_supportsAsyncFileStreams = supportsAsyncFileStreams;
|
_supportsAsyncFileStreams = supportsAsyncFileStreams;
|
||||||
|
EnableFileSystemRequestConcat = enableFileSystemRequestConcat;
|
||||||
SetInvalidFileNameChars(enableManagedInvalidFileNameChars);
|
SetInvalidFileNameChars(enableManagedInvalidFileNameChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
using MediaBrowser.Model.Logging;
|
|
||||||
|
|
||||||
namespace Emby.Common.Implementations.IO
|
|
||||||
{
|
|
||||||
public class WindowsFileSystem : ManagedFileSystem
|
|
||||||
{
|
|
||||||
public WindowsFileSystem(ILogger logger)
|
|
||||||
: base(logger, true, true)
|
|
||||||
{
|
|
||||||
EnableFileSystemRequestConcat = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -142,7 +142,7 @@ namespace Emby.Server.Core
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class CompositionRoot
|
/// Class CompositionRoot
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ApplicationHost : BaseApplicationHost<ServerApplicationPaths>, IServerApplicationHost, IDependencyContainer
|
public abstract class ApplicationHost : BaseApplicationHost<ServerApplicationPaths>, IServerApplicationHost, IDependencyContainer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the server configuration manager.
|
/// Gets the server configuration manager.
|
||||||
|
@ -257,11 +257,9 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
protected IAuthService AuthService { get; private set; }
|
protected IAuthService AuthService { get; private set; }
|
||||||
|
|
||||||
private readonly StartupOptions _startupOptions;
|
protected readonly StartupOptions StartupOptions;
|
||||||
private readonly string _releaseAssetFilename;
|
private readonly string _releaseAssetFilename;
|
||||||
|
|
||||||
internal INativeApp NativeApp { get; set; }
|
|
||||||
|
|
||||||
internal IPowerManagement PowerManagement { get; private set; }
|
internal IPowerManagement PowerManagement { get; private set; }
|
||||||
internal IImageEncoder ImageEncoder { get; private set; }
|
internal IImageEncoder ImageEncoder { get; private set; }
|
||||||
|
|
||||||
|
@ -275,7 +273,6 @@ namespace Emby.Server.Core
|
||||||
ILogManager logManager,
|
ILogManager logManager,
|
||||||
StartupOptions options,
|
StartupOptions options,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
INativeApp nativeApp,
|
|
||||||
IPowerManagement powerManagement,
|
IPowerManagement powerManagement,
|
||||||
string releaseAssetFilename,
|
string releaseAssetFilename,
|
||||||
IEnvironmentInfo environmentInfo,
|
IEnvironmentInfo environmentInfo,
|
||||||
|
@ -293,11 +290,10 @@ namespace Emby.Server.Core
|
||||||
memoryStreamFactory,
|
memoryStreamFactory,
|
||||||
networkManager)
|
networkManager)
|
||||||
{
|
{
|
||||||
_startupOptions = options;
|
StartupOptions = options;
|
||||||
_certificateGenerator = certificateGenerator;
|
_certificateGenerator = certificateGenerator;
|
||||||
_releaseAssetFilename = releaseAssetFilename;
|
_releaseAssetFilename = releaseAssetFilename;
|
||||||
_defaultUserNameFactory = defaultUsernameFactory;
|
_defaultUserNameFactory = defaultUsernameFactory;
|
||||||
NativeApp = nativeApp;
|
|
||||||
PowerManagement = powerManagement;
|
PowerManagement = powerManagement;
|
||||||
|
|
||||||
ImageEncoder = imageEncoder;
|
ImageEncoder = imageEncoder;
|
||||||
|
@ -314,19 +310,11 @@ namespace Emby.Server.Core
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _version ?? (_version = GetAssembly(NativeApp.GetType()).GetName().Version);
|
return _version ?? (_version = GetAssembly(GetType()).GetName().Version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsRunningAsService
|
public abstract bool SupportsRunningAsService { get; }
|
||||||
{
|
|
||||||
get { return NativeApp.IsRunningAsService; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SupportsRunningAsService
|
|
||||||
{
|
|
||||||
get { return NativeApp.SupportsRunningAsService; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the name.
|
/// Gets the name.
|
||||||
|
@ -345,19 +333,7 @@ namespace Emby.Server.Core
|
||||||
return type.GetTypeInfo().Assembly;
|
return type.GetTypeInfo().Assembly;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public abstract bool SupportsAutoRunAtStartup { get; }
|
||||||
/// Gets a value indicating whether this instance can self restart.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
|
|
||||||
public override bool CanSelfRestart
|
|
||||||
{
|
|
||||||
get { return NativeApp.CanSelfRestart; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SupportsAutoRunAtStartup
|
|
||||||
{
|
|
||||||
get { return NativeApp.SupportsAutoRunAtStartup; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetBaseExceptionMessage()
|
private void SetBaseExceptionMessage()
|
||||||
{
|
{
|
||||||
|
@ -580,11 +556,11 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
UserRepository = await GetUserRepository().ConfigureAwait(false);
|
UserRepository = await GetUserRepository().ConfigureAwait(false);
|
||||||
|
|
||||||
var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths, NativeApp.GetDbConnector(), MemoryStreamFactory);
|
var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths, GetDbConnector(), MemoryStreamFactory);
|
||||||
DisplayPreferencesRepository = displayPreferencesRepo;
|
DisplayPreferencesRepository = displayPreferencesRepo;
|
||||||
RegisterSingleInstance(DisplayPreferencesRepository);
|
RegisterSingleInstance(DisplayPreferencesRepository);
|
||||||
|
|
||||||
var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager, NativeApp.GetDbConnector(), MemoryStreamFactory);
|
var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager, GetDbConnector(), MemoryStreamFactory);
|
||||||
ItemRepository = itemRepo;
|
ItemRepository = itemRepo;
|
||||||
RegisterSingleInstance(ItemRepository);
|
RegisterSingleInstance(ItemRepository);
|
||||||
|
|
||||||
|
@ -707,7 +683,7 @@ namespace Emby.Server.Core
|
||||||
EncodingManager = new EncodingManager(FileSystemManager, Logger, MediaEncoder, ChapterManager, LibraryManager);
|
EncodingManager = new EncodingManager(FileSystemManager, Logger, MediaEncoder, ChapterManager, LibraryManager);
|
||||||
RegisterSingleInstance(EncodingManager);
|
RegisterSingleInstance(EncodingManager);
|
||||||
|
|
||||||
var sharingRepo = new SharingRepository(LogManager, ApplicationPaths, NativeApp.GetDbConnector());
|
var sharingRepo = new SharingRepository(LogManager, ApplicationPaths, GetDbConnector());
|
||||||
await sharingRepo.Initialize().ConfigureAwait(false);
|
await sharingRepo.Initialize().ConfigureAwait(false);
|
||||||
RegisterSingleInstance<ISharingManager>(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this));
|
RegisterSingleInstance<ISharingManager>(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this));
|
||||||
|
|
||||||
|
@ -727,7 +703,7 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
await displayPreferencesRepo.Initialize().ConfigureAwait(false);
|
await displayPreferencesRepo.Initialize().ConfigureAwait(false);
|
||||||
|
|
||||||
var userDataRepo = new SqliteUserDataRepository(LogManager, ApplicationPaths, NativeApp.GetDbConnector());
|
var userDataRepo = new SqliteUserDataRepository(LogManager, ApplicationPaths, GetDbConnector());
|
||||||
|
|
||||||
((UserDataManager)UserDataManager).Repository = userDataRepo;
|
((UserDataManager)UserDataManager).Repository = userDataRepo;
|
||||||
await itemRepo.Initialize(userDataRepo).ConfigureAwait(false);
|
await itemRepo.Initialize(userDataRepo).ConfigureAwait(false);
|
||||||
|
@ -770,14 +746,16 @@ namespace Emby.Server.Core
|
||||||
{
|
{
|
||||||
var maxConcurrentImageProcesses = Math.Max(Environment.ProcessorCount, 4);
|
var maxConcurrentImageProcesses = Math.Max(Environment.ProcessorCount, 4);
|
||||||
|
|
||||||
if (_startupOptions.ContainsOption("-imagethreads"))
|
if (StartupOptions.ContainsOption("-imagethreads"))
|
||||||
{
|
{
|
||||||
int.TryParse(_startupOptions.GetOption("-imagethreads"), NumberStyles.Any, CultureInfo.InvariantCulture, out maxConcurrentImageProcesses);
|
int.TryParse(StartupOptions.GetOption("-imagethreads"), NumberStyles.Any, CultureInfo.InvariantCulture, out maxConcurrentImageProcesses);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, maxConcurrentImageProcesses, () => LibraryManager, TimerFactory);
|
return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, maxConcurrentImageProcesses, () => LibraryManager, TimerFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract FFMpegInstallInfo GetFfmpegInstallInfo();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers the media encoder.
|
/// Registers the media encoder.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -787,8 +765,8 @@ namespace Emby.Server.Core
|
||||||
string encoderPath = null;
|
string encoderPath = null;
|
||||||
string probePath = null;
|
string probePath = null;
|
||||||
|
|
||||||
var info = await new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.GetFfmpegInstallInfo())
|
var info = await new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, GetFfmpegInstallInfo())
|
||||||
.GetFFMpegInfo(_startupOptions, progress).ConfigureAwait(false);
|
.GetFFMpegInfo(StartupOptions, progress).ConfigureAwait(false);
|
||||||
|
|
||||||
encoderPath = info.EncoderPath;
|
encoderPath = info.EncoderPath;
|
||||||
probePath = info.ProbePath;
|
probePath = info.ProbePath;
|
||||||
|
@ -825,7 +803,7 @@ namespace Emby.Server.Core
|
||||||
/// <returns>Task{IUserRepository}.</returns>
|
/// <returns>Task{IUserRepository}.</returns>
|
||||||
private async Task<IUserRepository> GetUserRepository()
|
private async Task<IUserRepository> GetUserRepository()
|
||||||
{
|
{
|
||||||
var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer, NativeApp.GetDbConnector(), MemoryStreamFactory);
|
var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer, GetDbConnector(), MemoryStreamFactory);
|
||||||
|
|
||||||
await repo.Initialize().ConfigureAwait(false);
|
await repo.Initialize().ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -838,7 +816,7 @@ namespace Emby.Server.Core
|
||||||
/// <returns>Task{IUserRepository}.</returns>
|
/// <returns>Task{IUserRepository}.</returns>
|
||||||
private async Task<IFileOrganizationRepository> GetFileOrganizationRepository()
|
private async Task<IFileOrganizationRepository> GetFileOrganizationRepository()
|
||||||
{
|
{
|
||||||
var repo = new SqliteFileOrganizationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector());
|
var repo = new SqliteFileOrganizationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, GetDbConnector());
|
||||||
|
|
||||||
await repo.Initialize().ConfigureAwait(false);
|
await repo.Initialize().ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -847,7 +825,7 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
private async Task<IAuthenticationRepository> GetAuthenticationRepository()
|
private async Task<IAuthenticationRepository> GetAuthenticationRepository()
|
||||||
{
|
{
|
||||||
var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector());
|
var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, GetDbConnector());
|
||||||
|
|
||||||
await repo.Initialize().ConfigureAwait(false);
|
await repo.Initialize().ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -856,7 +834,7 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
private async Task<IActivityRepository> GetActivityLogRepository()
|
private async Task<IActivityRepository> GetActivityLogRepository()
|
||||||
{
|
{
|
||||||
var repo = new ActivityRepository(LogManager, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector());
|
var repo = new ActivityRepository(LogManager, ServerConfigurationManager.ApplicationPaths, GetDbConnector());
|
||||||
|
|
||||||
await repo.Initialize().ConfigureAwait(false);
|
await repo.Initialize().ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -865,7 +843,7 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
private async Task<ISyncRepository> GetSyncRepository()
|
private async Task<ISyncRepository> GetSyncRepository()
|
||||||
{
|
{
|
||||||
var repo = new SyncRepository(LogManager, JsonSerializer, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector());
|
var repo = new SyncRepository(LogManager, JsonSerializer, ServerConfigurationManager.ApplicationPaths, GetDbConnector());
|
||||||
|
|
||||||
await repo.Initialize().ConfigureAwait(false);
|
await repo.Initialize().ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -877,7 +855,7 @@ namespace Emby.Server.Core
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task ConfigureNotificationsRepository()
|
private async Task ConfigureNotificationsRepository()
|
||||||
{
|
{
|
||||||
var repo = new SqliteNotificationsRepository(LogManager, ApplicationPaths, NativeApp.GetDbConnector());
|
var repo = new SqliteNotificationsRepository(LogManager, ApplicationPaths, GetDbConnector());
|
||||||
|
|
||||||
await repo.Initialize().ConfigureAwait(false);
|
await repo.Initialize().ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -1123,24 +1101,12 @@ namespace Emby.Server.Core
|
||||||
Logger.ErrorException("Error sending server restart notification", ex);
|
Logger.ErrorException("Error sending server restart notification", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info("Calling NativeApp.Restart");
|
Logger.Info("Calling RestartInternal");
|
||||||
|
|
||||||
NativeApp.Restart(_startupOptions);
|
RestartInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
protected abstract void RestartInternal();
|
||||||
/// Gets or sets a value indicating whether this instance can self update.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value>
|
|
||||||
public override bool CanSelfUpdate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
#pragma warning disable 162
|
|
||||||
return NativeApp.CanSelfUpdate;
|
|
||||||
#pragma warning restore 162
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the composable part assemblies.
|
/// Gets the composable part assemblies.
|
||||||
|
@ -1196,14 +1162,16 @@ namespace Emby.Server.Core
|
||||||
// Xbmc
|
// Xbmc
|
||||||
list.Add(GetAssembly(typeof(ArtistNfoProvider)));
|
list.Add(GetAssembly(typeof(ArtistNfoProvider)));
|
||||||
|
|
||||||
list.AddRange(NativeApp.GetAssembliesWithParts());
|
list.AddRange(GetAssembliesWithPartsInternal());
|
||||||
|
|
||||||
// Include composable parts in the running assembly
|
// Include composable parts in the running assembly
|
||||||
list.Add(GetAssembly(GetType()));
|
list.Add(GetAssembly(typeof(ApplicationHost)));
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract List<Assembly> GetAssembliesWithPartsInternal();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin assemblies.
|
/// Gets the plugin assemblies.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1280,7 +1248,7 @@ namespace Emby.Server.Core
|
||||||
EncoderLocationType = MediaEncoder.EncoderLocationType,
|
EncoderLocationType = MediaEncoder.EncoderLocationType,
|
||||||
SystemArchitecture = EnvironmentInfo.SystemArchitecture,
|
SystemArchitecture = EnvironmentInfo.SystemArchitecture,
|
||||||
SystemUpdateLevel = ConfigurationManager.CommonConfiguration.SystemUpdateLevel,
|
SystemUpdateLevel = ConfigurationManager.CommonConfiguration.SystemUpdateLevel,
|
||||||
PackageName = _startupOptions.GetOption("-package")
|
PackageName = StartupOptions.GetOption("-package")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1456,9 +1424,11 @@ namespace Emby.Server.Core
|
||||||
Logger.ErrorException("Error sending server shutdown notification", ex);
|
Logger.ErrorException("Error sending server shutdown notification", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeApp.Shutdown();
|
ShutdownInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void ShutdownInternal();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Registers the server with administrator access.
|
/// Registers the server with administrator access.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1468,7 +1438,7 @@ namespace Emby.Server.Core
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
NativeApp.AuthorizeServer(
|
AuthorizeServer(
|
||||||
UdpServerEntryPoint.PortNumber,
|
UdpServerEntryPoint.PortNumber,
|
||||||
ServerConfigurationManager.Configuration.HttpServerPortNumber,
|
ServerConfigurationManager.Configuration.HttpServerPortNumber,
|
||||||
ServerConfigurationManager.Configuration.HttpsPortNumber,
|
ServerConfigurationManager.Configuration.HttpsPortNumber,
|
||||||
|
@ -1481,6 +1451,9 @@ namespace Emby.Server.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory);
|
||||||
|
protected abstract IDbConnector GetDbConnector();
|
||||||
|
|
||||||
public event EventHandler HasUpdateAvailableChanged;
|
public event EventHandler HasUpdateAvailableChanged;
|
||||||
|
|
||||||
private bool _hasUpdateAvailable;
|
private bool _hasUpdateAvailable;
|
||||||
|
@ -1551,10 +1524,12 @@ namespace Emby.Server.Core
|
||||||
{
|
{
|
||||||
if (SupportsAutoRunAtStartup)
|
if (SupportsAutoRunAtStartup)
|
||||||
{
|
{
|
||||||
NativeApp.ConfigureAutoRun(autorun);
|
ConfigureAutoRunInternal(autorun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void ConfigureAutoRunInternal(bool autorun);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This returns localhost in the case of no external dns, and the hostname if the
|
/// This returns localhost in the case of no external dns, and the hostname if the
|
||||||
/// dns is prefixed with a valid Uri prefix.
|
/// dns is prefixed with a valid Uri prefix.
|
||||||
|
@ -1578,16 +1553,15 @@ namespace Emby.Server.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LaunchUrl(string url)
|
public abstract void LaunchUrl(string url);
|
||||||
{
|
|
||||||
NativeApp.LaunchUrl(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnableLoopback(string appName)
|
public void EnableLoopback(string appName)
|
||||||
{
|
{
|
||||||
NativeApp.EnableLoopback(appName);
|
EnableLoopbackInternal(appName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void EnableLoopbackInternal(string appName);
|
||||||
|
|
||||||
private void RegisterModules()
|
private void RegisterModules()
|
||||||
{
|
{
|
||||||
var moduleTypes = GetExportTypes<IDependencyModule>();
|
var moduleTypes = GetExportTypes<IDependencyModule>();
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Model.Logging;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using Emby.Server.Core;
|
|
||||||
using Emby.Server.Core.Data;
|
|
||||||
using Emby.Server.Core.FFMpeg;
|
|
||||||
|
|
||||||
namespace Emby.Server.Core
|
|
||||||
{
|
|
||||||
public interface INativeApp
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the assemblies with parts.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>List<Assembly>.</returns>
|
|
||||||
List<Assembly> GetAssembliesWithParts();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Authorizes the server.
|
|
||||||
/// </summary>
|
|
||||||
void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether [supports running as service].
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if [supports running as service]; otherwise, <c>false</c>.</value>
|
|
||||||
bool SupportsRunningAsService { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this instance is running as service.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance is running as service; otherwise, <c>false</c>.</value>
|
|
||||||
bool IsRunningAsService { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this instance can self restart.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
|
|
||||||
bool CanSelfRestart { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether [supports autorun at startup].
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if [supports autorun at startup]; otherwise, <c>false</c>.</value>
|
|
||||||
bool SupportsAutoRunAtStartup { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this instance can self update.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value>
|
|
||||||
bool CanSelfUpdate { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shutdowns this instance.
|
|
||||||
/// </summary>
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restarts this instance.
|
|
||||||
/// </summary>
|
|
||||||
void Restart(StartupOptions startupOptions);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Configures the automatic run.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="autorun">if set to <c>true</c> [autorun].</param>
|
|
||||||
void ConfigureAutoRun(bool autorun);
|
|
||||||
|
|
||||||
FFMpegInstallInfo GetFfmpegInstallInfo();
|
|
||||||
|
|
||||||
void LaunchUrl(string url);
|
|
||||||
|
|
||||||
IDbConnector GetDbConnector();
|
|
||||||
|
|
||||||
void EnableLoopback(string appName);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -106,7 +106,7 @@
|
||||||
<Compile Include="..\SharedVersion.cs">
|
<Compile Include="..\SharedVersion.cs">
|
||||||
<Link>Properties\SharedVersion.cs</Link>
|
<Link>Properties\SharedVersion.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Native\MonoApp.cs" />
|
<Compile Include="MonoAppHost.cs" />
|
||||||
<Compile Include="Native\DbConnector.cs" />
|
<Compile Include="Native\DbConnector.cs" />
|
||||||
<Compile Include="Native\MonoFileSystem.cs" />
|
<Compile Include="Native\MonoFileSystem.cs" />
|
||||||
<Compile Include="Native\PowerManagement.cs" />
|
<Compile Include="Native\PowerManagement.cs" />
|
||||||
|
|
139
MediaBrowser.Server.Mono/MonoAppHost.cs
Normal file
139
MediaBrowser.Server.Mono/MonoAppHost.cs
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Emby.Server.Core;
|
||||||
|
using Emby.Server.Core.Data;
|
||||||
|
using Emby.Server.Core.FFMpeg;
|
||||||
|
using MediaBrowser.IsoMounter;
|
||||||
|
using MediaBrowser.Model.IO;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
using MediaBrowser.Model.System;
|
||||||
|
using MediaBrowser.Server.Mono.Native;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Server.Mono
|
||||||
|
{
|
||||||
|
public class MonoAppHost : ApplicationHost
|
||||||
|
{
|
||||||
|
public MonoAppHost(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 CanSelfRestart
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// A restart script must be provided
|
||||||
|
return StartupOptions.ContainsOption("-restartpath");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanSelfUpdate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override FFMpegInstallInfo GetFfmpegInstallInfo()
|
||||||
|
{
|
||||||
|
var info = new FFMpegInstallInfo();
|
||||||
|
|
||||||
|
// Windows builds: http://ffmpeg.zeranoe.com/builds/
|
||||||
|
// Linux builds: http://johnvansickle.com/ffmpeg/
|
||||||
|
// OS X builds: http://ffmpegmac.net/
|
||||||
|
// OS X x64: http://www.evermeet.cx/ffmpeg/
|
||||||
|
|
||||||
|
var environment = (MonoEnvironmentInfo) EnvironmentInfo;
|
||||||
|
|
||||||
|
if (environment.IsBsd)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (environment.OperatingSystem == Model.System.OperatingSystem.Linux)
|
||||||
|
{
|
||||||
|
info.ArchiveType = "7z";
|
||||||
|
info.Version = "20160215";
|
||||||
|
}
|
||||||
|
|
||||||
|
// No version available - user requirement
|
||||||
|
info.DownloadUrls = new string[] { };
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RestartInternal()
|
||||||
|
{
|
||||||
|
MainClass.Restart(StartupOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override List<Assembly> GetAssembliesWithPartsInternal()
|
||||||
|
{
|
||||||
|
var list = new List<Assembly>();
|
||||||
|
|
||||||
|
list.Add(GetType().Assembly);
|
||||||
|
list.AddRange(GetLinuxAssemblies());
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Assembly> GetLinuxAssemblies()
|
||||||
|
{
|
||||||
|
var list = new List<Assembly>();
|
||||||
|
|
||||||
|
list.Add(typeof(LinuxIsoManager).Assembly);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ShutdownInternal()
|
||||||
|
{
|
||||||
|
MainClass.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IDbConnector GetDbConnector()
|
||||||
|
{
|
||||||
|
return new DbConnector(Logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ConfigureAutoRunInternal(bool autorun)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LaunchUrl(string url)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void EnableLoopbackInternal(string appName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool SupportsRunningAsService
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool SupportsAutoRunAtStartup
|
||||||
|
{
|
||||||
|
get { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsRunningAsService
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,164 +0,0 @@
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.IsoMounter;
|
|
||||||
using MediaBrowser.Model.Logging;
|
|
||||||
using MediaBrowser.Server.Startup.Common;
|
|
||||||
using Mono.Unix.Native;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using Emby.Common.Implementations.Networking;
|
|
||||||
using Emby.Server.Core;
|
|
||||||
using Emby.Server.Core.Data;
|
|
||||||
using Emby.Server.Core.FFMpeg;
|
|
||||||
using MediaBrowser.Model.System;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Server.Mono.Native
|
|
||||||
{
|
|
||||||
public class MonoApp : INativeApp
|
|
||||||
{
|
|
||||||
protected StartupOptions StartupOptions { get; private set; }
|
|
||||||
protected ILogger Logger { get; private set; }
|
|
||||||
private readonly MonoEnvironmentInfo _environment;
|
|
||||||
|
|
||||||
public MonoApp(StartupOptions startupOptions, ILogger logger, MonoEnvironmentInfo environment)
|
|
||||||
{
|
|
||||||
StartupOptions = startupOptions;
|
|
||||||
Logger = logger;
|
|
||||||
_environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shutdowns this instance.
|
|
||||||
/// </summary>
|
|
||||||
public void Shutdown()
|
|
||||||
{
|
|
||||||
MainClass.Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether this instance [can self restart].
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
|
|
||||||
public bool CanSelfRestart
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
// A restart script must be provided
|
|
||||||
return StartupOptions.ContainsOption("-restartpath");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restarts this instance.
|
|
||||||
/// </summary>
|
|
||||||
public void Restart(StartupOptions startupOptions)
|
|
||||||
{
|
|
||||||
MainClass.Restart(startupOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this instance can self update.
|
|
||||||
/// </summary>
|
|
||||||
/// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value>
|
|
||||||
public bool CanSelfUpdate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SupportsAutoRunAtStartup
|
|
||||||
{
|
|
||||||
get { return false; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Assembly> GetAssembliesWithParts()
|
|
||||||
{
|
|
||||||
var list = new List<Assembly>();
|
|
||||||
|
|
||||||
list.Add(GetType().Assembly);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<Assembly> GetLinuxAssemblies()
|
|
||||||
{
|
|
||||||
var list = new List<Assembly>();
|
|
||||||
|
|
||||||
//list.Add(typeof(LinuxIsoManager).Assembly);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AuthorizeServer(int udpPort, int httpServerPort, int httpsPort, string applicationPath, string tempDirectory)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SupportsRunningAsService
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsRunningAsService
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ConfigureAutoRun(bool autorun)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public INetworkManager CreateNetworkManager(ILogger logger)
|
|
||||||
{
|
|
||||||
return new NetworkManager(logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FFMpegInstallInfo GetFfmpegInstallInfo()
|
|
||||||
{
|
|
||||||
var info = new FFMpegInstallInfo();
|
|
||||||
|
|
||||||
// Windows builds: http://ffmpeg.zeranoe.com/builds/
|
|
||||||
// Linux builds: http://johnvansickle.com/ffmpeg/
|
|
||||||
// OS X builds: http://ffmpegmac.net/
|
|
||||||
// OS X x64: http://www.evermeet.cx/ffmpeg/
|
|
||||||
|
|
||||||
if (_environment.IsBsd)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (_environment.OperatingSystem == Model.System.OperatingSystem.Linux)
|
|
||||||
{
|
|
||||||
info.ArchiveType = "7z";
|
|
||||||
info.Version = "20160215";
|
|
||||||
}
|
|
||||||
|
|
||||||
// No version available - user requirement
|
|
||||||
info.DownloadUrls = new string[] { };
|
|
||||||
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LaunchUrl(string url)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDbConnector GetDbConnector()
|
|
||||||
{
|
|
||||||
return new DbConnector(Logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void EnableLoopback(string appName)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@ namespace MediaBrowser.Server.Mono.Native
|
||||||
{
|
{
|
||||||
public class MonoFileSystem : ManagedFileSystem
|
public class MonoFileSystem : ManagedFileSystem
|
||||||
{
|
{
|
||||||
public MonoFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars) : base(logger, supportsAsyncFileStreams, enableManagedInvalidFileNameChars)
|
public MonoFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars) : base(logger, supportsAsyncFileStreams, enableManagedInvalidFileNameChars, false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,15 +91,12 @@ namespace MediaBrowser.Server.Mono
|
||||||
|
|
||||||
var environmentInfo = GetEnvironmentInfo();
|
var environmentInfo = GetEnvironmentInfo();
|
||||||
|
|
||||||
var nativeApp = new MonoApp(options, logManager.GetLogger("App"), environmentInfo);
|
|
||||||
|
|
||||||
var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths);
|
var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths);
|
||||||
|
|
||||||
_appHost = new ApplicationHost(appPaths,
|
_appHost = new MonoAppHost(appPaths,
|
||||||
logManager,
|
logManager,
|
||||||
options,
|
options,
|
||||||
fileSystem,
|
fileSystem,
|
||||||
nativeApp,
|
|
||||||
new PowerManagement(),
|
new PowerManagement(),
|
||||||
"emby.mono.zip",
|
"emby.mono.zip",
|
||||||
environmentInfo,
|
environmentInfo,
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
private static ILogger _logger;
|
private static ILogger _logger;
|
||||||
|
|
||||||
private static bool _isRunningAsService = false;
|
public static bool IsRunningAsService = false;
|
||||||
private static bool _canRestartService = false;
|
private static bool _canRestartService = false;
|
||||||
private static bool _appHostDisposed;
|
private static bool _appHostDisposed;
|
||||||
|
|
||||||
|
@ -72,9 +72,9 @@ namespace MediaBrowser.ServerApplication
|
||||||
public static void Main()
|
public static void Main()
|
||||||
{
|
{
|
||||||
var options = new StartupOptions();
|
var options = new StartupOptions();
|
||||||
_isRunningAsService = options.ContainsOption("-service");
|
IsRunningAsService = options.ContainsOption("-service");
|
||||||
|
|
||||||
if (_isRunningAsService)
|
if (IsRunningAsService)
|
||||||
{
|
{
|
||||||
//_canRestartService = CanRestartWindowsService();
|
//_canRestartService = CanRestartWindowsService();
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
var success = SetDllDirectory(architecturePath);
|
var success = SetDllDirectory(architecturePath);
|
||||||
|
|
||||||
var appPaths = CreateApplicationPaths(applicationPath, _isRunningAsService);
|
var appPaths = CreateApplicationPaths(applicationPath, IsRunningAsService);
|
||||||
|
|
||||||
var logManager = new NlogManager(appPaths.LogDirectoryPath, "server");
|
var logManager = new NlogManager(appPaths.LogDirectoryPath, "server");
|
||||||
logManager.ReloadLogger(LogSeverity.Debug);
|
logManager.ReloadLogger(LogSeverity.Debug);
|
||||||
|
@ -148,7 +148,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RunApplication(appPaths, logManager, _isRunningAsService, options);
|
RunApplication(appPaths, logManager, IsRunningAsService, options);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -204,7 +204,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_isRunningAsService)
|
if (!IsRunningAsService)
|
||||||
{
|
{
|
||||||
return IsAlreadyRunningAsService(applicationPath);
|
return IsAlreadyRunningAsService(applicationPath);
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
if (_isRunningAsService)
|
if (IsRunningAsService)
|
||||||
{
|
{
|
||||||
return _canRestartService;
|
return _canRestartService;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (_isRunningAsService)
|
if (IsRunningAsService)
|
||||||
{
|
{
|
||||||
return _canRestartService;
|
return _canRestartService;
|
||||||
}
|
}
|
||||||
|
@ -317,22 +317,16 @@ namespace MediaBrowser.ServerApplication
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, bool runService, StartupOptions options)
|
private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, bool runService, StartupOptions options)
|
||||||
{
|
{
|
||||||
var fileSystem = new WindowsFileSystem(logManager.GetLogger("FileSystem"));
|
var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), true, true, true);
|
||||||
fileSystem.AddShortcutHandler(new LnkShortcutHandler());
|
fileSystem.AddShortcutHandler(new LnkShortcutHandler());
|
||||||
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
|
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
|
||||||
|
|
||||||
var nativeApp = new WindowsApp(fileSystem, _logger)
|
|
||||||
{
|
|
||||||
IsRunningAsService = runService
|
|
||||||
};
|
|
||||||
|
|
||||||
var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths);
|
var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths);
|
||||||
|
|
||||||
_appHost = new ApplicationHost(appPaths,
|
_appHost = new WindowsAppHost(appPaths,
|
||||||
logManager,
|
logManager,
|
||||||
options,
|
options,
|
||||||
fileSystem,
|
fileSystem,
|
||||||
nativeApp,
|
|
||||||
new PowerManagement(),
|
new PowerManagement(),
|
||||||
"emby.windows.zip",
|
"emby.windows.zip",
|
||||||
new EnvironmentInfo(),
|
new EnvironmentInfo(),
|
||||||
|
@ -440,7 +434,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
public static void Invoke(Action action)
|
public static void Invoke(Action action)
|
||||||
{
|
{
|
||||||
if (_isRunningAsService)
|
if (IsRunningAsService)
|
||||||
{
|
{
|
||||||
action();
|
action();
|
||||||
}
|
}
|
||||||
|
@ -578,7 +572,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
/// <param name="e">The <see cref="SessionEndingEventArgs"/> instance containing the event data.</param>
|
/// <param name="e">The <see cref="SessionEndingEventArgs"/> instance containing the event data.</param>
|
||||||
static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
|
static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Reason == SessionEndReasons.SystemShutdown || !_isRunningAsService)
|
if (e.Reason == SessionEndReasons.SystemShutdown || !IsRunningAsService)
|
||||||
{
|
{
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
|
@ -595,7 +589,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
new UnhandledExceptionWriter(_appHost.ServerConfigurationManager.ApplicationPaths, _logger, _appHost.LogManager).Log(exception);
|
new UnhandledExceptionWriter(_appHost.ServerConfigurationManager.ApplicationPaths, _logger, _appHost.LogManager).Log(exception);
|
||||||
|
|
||||||
if (!_isRunningAsService)
|
if (!IsRunningAsService)
|
||||||
{
|
{
|
||||||
MessageBox.Show("Unhandled exception: " + exception.Message);
|
MessageBox.Show("Unhandled exception: " + exception.Message);
|
||||||
}
|
}
|
||||||
|
@ -623,7 +617,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
// Update is there - execute update
|
// Update is there - execute update
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty;
|
var serviceName = IsRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty;
|
||||||
new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName);
|
new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName);
|
||||||
|
|
||||||
// And just let the app exit so it can update
|
// And just let the app exit so it can update
|
||||||
|
@ -642,7 +636,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
|
|
||||||
public static void Shutdown()
|
public static void Shutdown()
|
||||||
{
|
{
|
||||||
if (_isRunningAsService)
|
if (IsRunningAsService)
|
||||||
{
|
{
|
||||||
ShutdownWindowsService();
|
ShutdownWindowsService();
|
||||||
}
|
}
|
||||||
|
@ -658,7 +652,7 @@ namespace MediaBrowser.ServerApplication
|
||||||
{
|
{
|
||||||
DisposeAppHost();
|
DisposeAppHost();
|
||||||
|
|
||||||
if (_isRunningAsService)
|
if (IsRunningAsService)
|
||||||
{
|
{
|
||||||
RestartWindowsService();
|
RestartWindowsService();
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,6 @@
|
||||||
<Compile Include="Native\PowerManagement.cs" />
|
<Compile Include="Native\PowerManagement.cs" />
|
||||||
<Compile Include="Native\Standby.cs" />
|
<Compile Include="Native\Standby.cs" />
|
||||||
<Compile Include="Native\ServerAuthorization.cs" />
|
<Compile Include="Native\ServerAuthorization.cs" />
|
||||||
<Compile Include="Native\WindowsApp.cs" />
|
|
||||||
<Compile Include="Networking\NativeMethods.cs" />
|
<Compile Include="Networking\NativeMethods.cs" />
|
||||||
<Compile Include="Networking\NetworkManager.cs" />
|
<Compile Include="Networking\NetworkManager.cs" />
|
||||||
<Compile Include="Networking\NetworkShares.cs" />
|
<Compile Include="Networking\NetworkShares.cs" />
|
||||||
|
@ -156,6 +155,7 @@
|
||||||
<DependentUpon>SplashForm.cs</DependentUpon>
|
<DependentUpon>SplashForm.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Updates\ApplicationUpdater.cs" />
|
<Compile Include="Updates\ApplicationUpdater.cs" />
|
||||||
|
<Compile Include="WindowsAppHost.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="App.config" />
|
<None Include="App.config" />
|
||||||
|
|
|
@ -1,131 +1,31 @@
|
||||||
using System;
|
using System;
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using MediaBrowser.Model.Logging;
|
|
||||||
using MediaBrowser.Server.Startup.Common;
|
|
||||||
using MediaBrowser.ServerApplication.Networking;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Windows.Forms;
|
|
||||||
using Emby.Server.Core;
|
using Emby.Server.Core;
|
||||||
using Emby.Server.Core.Data;
|
using Emby.Server.Core.Data;
|
||||||
using Emby.Server.Core.FFMpeg;
|
using Emby.Server.Core.FFMpeg;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Controller.IO;
|
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
using MediaBrowser.Model.System;
|
||||||
|
using MediaBrowser.ServerApplication.Native;
|
||||||
|
|
||||||
namespace MediaBrowser.ServerApplication.Native
|
namespace MediaBrowser.ServerApplication
|
||||||
{
|
{
|
||||||
public class WindowsApp : INativeApp
|
public class WindowsAppHost : ApplicationHost
|
||||||
{
|
{
|
||||||
private readonly IFileSystem _fileSystem;
|
public WindowsAppHost(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)
|
||||||
private readonly ILogger _logger;
|
: base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory)
|
||||||
|
|
||||||
public WindowsApp(IFileSystem fileSystem, ILogger logger)
|
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Assembly> GetAssembliesWithParts()
|
public override bool IsRunningAsService
|
||||||
{
|
{
|
||||||
var list = new List<Assembly>();
|
get { return MainStartup.IsRunningAsService; }
|
||||||
|
|
||||||
if (!System.Environment.Is64BitProcess)
|
|
||||||
{
|
|
||||||
//list.Add(typeof(PismoIsoManager).Assembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
list.Add(GetType().Assembly);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AuthorizeServer(int udpPort, int httpServerPort, int httpsPort, string applicationPath, string tempDirectory)
|
protected override FFMpegInstallInfo GetFfmpegInstallInfo()
|
||||||
{
|
|
||||||
ServerAuthorization.AuthorizeServer(udpPort, httpServerPort, httpsPort, applicationPath, tempDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SupportsLibraryMonitor
|
|
||||||
{
|
|
||||||
get { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SupportsRunningAsService
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsRunningAsService
|
|
||||||
{
|
|
||||||
get;
|
|
||||||
set;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanSelfRestart
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return MainStartup.CanSelfRestart;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SupportsAutoRunAtStartup
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanSelfUpdate
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return MainStartup.CanSelfUpdate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Shutdown()
|
|
||||||
{
|
|
||||||
MainStartup.Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Restart(StartupOptions startupOptions)
|
|
||||||
{
|
|
||||||
MainStartup.Restart();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ConfigureAutoRun(bool autorun)
|
|
||||||
{
|
|
||||||
var shortcutPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk");
|
|
||||||
|
|
||||||
var startupPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup);
|
|
||||||
|
|
||||||
if (autorun)
|
|
||||||
{
|
|
||||||
//Copy our shortut into the startup folder for this user
|
|
||||||
var targetPath = Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk");
|
|
||||||
_fileSystem.CreateDirectory(Path.GetDirectoryName(targetPath));
|
|
||||||
File.Copy(shortcutPath, targetPath, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Remove our shortcut from the startup folder for this user
|
|
||||||
_fileSystem.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public INetworkManager CreateNetworkManager(ILogger logger)
|
|
||||||
{
|
|
||||||
return new NetworkManager(logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FFMpegInstallInfo GetFfmpegInstallInfo()
|
|
||||||
{
|
{
|
||||||
var info = new FFMpegInstallInfo();
|
var info = new FFMpegInstallInfo();
|
||||||
|
|
||||||
|
@ -136,7 +36,61 @@ namespace MediaBrowser.ServerApplication.Native
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LaunchUrl(string url)
|
protected override void RestartInternal()
|
||||||
|
{
|
||||||
|
MainStartup.Restart();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override List<Assembly> GetAssembliesWithPartsInternal()
|
||||||
|
{
|
||||||
|
var list = new List<Assembly>();
|
||||||
|
|
||||||
|
if (!Environment.Is64BitProcess)
|
||||||
|
{
|
||||||
|
//list.Add(typeof(PismoIsoManager).Assembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add(GetType().Assembly);
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ShutdownInternal()
|
||||||
|
{
|
||||||
|
MainStartup.Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory)
|
||||||
|
{
|
||||||
|
ServerAuthorization.AuthorizeServer(udpPort, httpServerPort, httpsServerPort, applicationPath, tempDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IDbConnector GetDbConnector()
|
||||||
|
{
|
||||||
|
return new DbConnector(Logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ConfigureAutoRunInternal(bool autorun)
|
||||||
|
{
|
||||||
|
var shortcutPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk");
|
||||||
|
|
||||||
|
var startupPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup);
|
||||||
|
|
||||||
|
if (autorun)
|
||||||
|
{
|
||||||
|
//Copy our shortut into the startup folder for this user
|
||||||
|
var targetPath = Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk");
|
||||||
|
FileSystemManager.CreateDirectory(Path.GetDirectoryName(targetPath));
|
||||||
|
File.Copy(shortcutPath, targetPath, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Remove our shortcut from the startup folder for this user
|
||||||
|
FileSystemManager.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LaunchUrl(string url)
|
||||||
{
|
{
|
||||||
var process = new Process
|
var process = new Process
|
||||||
{
|
{
|
||||||
|
@ -156,32 +110,54 @@ namespace MediaBrowser.ServerApplication.Native
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error launching url: {0}", ex, url);
|
Logger.ErrorException("Error launching url: {0}", ex, url);
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDbConnector GetDbConnector()
|
|
||||||
{
|
|
||||||
return new DbConnector(_logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Processes the exited.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender">The sender.</param>
|
|
||||||
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
|
||||||
private static void ProcessExited(object sender, EventArgs e)
|
private static void ProcessExited(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
((Process)sender).Dispose();
|
((Process)sender).Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnableLoopback(string appName)
|
protected override void EnableLoopbackInternal(string appName)
|
||||||
{
|
{
|
||||||
LoopUtil.Run(appName);
|
LoopUtil.Run(appName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool SupportsRunningAsService
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanSelfRestart
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return MainStartup.CanSelfRestart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool SupportsAutoRunAtStartup
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanSelfUpdate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return MainStartup.CanSelfUpdate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool PortsRequireAuthorization(string applicationPath)
|
public bool PortsRequireAuthorization(string applicationPath)
|
||||||
{
|
{
|
||||||
var appNameSrch = Path.GetFileName(applicationPath);
|
var appNameSrch = Path.GetFileName(applicationPath);
|
||||||
|
@ -209,7 +185,7 @@ namespace MediaBrowser.ServerApplication.Native
|
||||||
|
|
||||||
if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1)
|
if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
_logger.Info("Found potential windows firewall rule blocking Emby Server: " + data);
|
Logger.Info("Found potential windows firewall rule blocking Emby Server: " + data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//var parts = data.Split('\n');
|
//var parts = data.Split('\n');
|
||||||
|
@ -220,7 +196,7 @@ namespace MediaBrowser.ServerApplication.Native
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error querying windows firewall", ex);
|
Logger.ErrorException("Error querying windows firewall", ex);
|
||||||
|
|
||||||
// Hate having to do this
|
// Hate having to do this
|
||||||
try
|
try
|
||||||
|
@ -229,12 +205,13 @@ namespace MediaBrowser.ServerApplication.Native
|
||||||
}
|
}
|
||||||
catch (Exception ex1)
|
catch (Exception ex1)
|
||||||
{
|
{
|
||||||
_logger.ErrorException("Error killing process", ex1);
|
Logger.ErrorException("Error killing process", ex1);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
47
src/Emby.Server/ApplicationPathHelper.cs
Normal file
47
src/Emby.Server/ApplicationPathHelper.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
107
src/Emby.Server/CoreAppHost.cs
Normal file
107
src/Emby.Server/CoreAppHost.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/Emby.Server/CoreSystemEvents.cs
Normal file
11
src/Emby.Server/CoreSystemEvents.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
52
src/Emby.Server/Data/DbConnector.cs
Normal file
52
src/Emby.Server/Data/DbConnector.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
src/Emby.Server/IO/MemoryStreamFactory.cs
Normal file
33
src/Emby.Server/IO/MemoryStreamFactory.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
src/Emby.Server/PowerManagement.cs
Normal file
15
src/Emby.Server/PowerManagement.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using MediaBrowser.Model.System;
|
||||||
|
|
||||||
|
namespace Emby.Server
|
||||||
|
{
|
||||||
|
public class PowerManagement : IPowerManagement
|
||||||
|
{
|
||||||
|
public void PreventSystemStandby()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AllowSystemStandby()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,33 +1,24 @@
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Server.Implementations;
|
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 Microsoft.Win32;
|
||||||
using System;
|
using System;
|
||||||
using System.Configuration.Install;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Management;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.ServiceProcess;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
|
||||||
using Emby.Common.Implementations.EnvironmentInfo;
|
using Emby.Common.Implementations.EnvironmentInfo;
|
||||||
using Emby.Common.Implementations.IO;
|
using Emby.Common.Implementations.IO;
|
||||||
using Emby.Common.Implementations.Logging;
|
using Emby.Common.Implementations.Logging;
|
||||||
using Emby.Common.Implementations.Networking;
|
using Emby.Common.Implementations.Networking;
|
||||||
using Emby.Common.Implementations.Security;
|
using Emby.Drawing;
|
||||||
using Emby.Server.Core;
|
using Emby.Server.Core;
|
||||||
using Emby.Server.Core.Browser;
|
using Emby.Server.Core.Browser;
|
||||||
using Emby.Server.Implementations.IO;
|
using Emby.Server.Implementations.IO;
|
||||||
using ImageMagickSharp;
|
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Server.Startup.Common.IO;
|
using Emby.Server.IO;
|
||||||
|
|
||||||
namespace Emby.Server
|
namespace Emby.Server
|
||||||
{
|
{
|
||||||
|
@ -60,11 +51,11 @@ namespace Emby.Server
|
||||||
var currentProcess = Process.GetCurrentProcess();
|
var currentProcess = Process.GetCurrentProcess();
|
||||||
|
|
||||||
var applicationPath = currentProcess.MainModule.FileName;
|
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);
|
var appPaths = CreateApplicationPaths(applicationPath, _isRunningAsService);
|
||||||
|
|
||||||
|
@ -227,31 +218,25 @@ namespace Emby.Server
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, bool runService, StartupOptions options)
|
private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, bool runService, StartupOptions options)
|
||||||
{
|
{
|
||||||
var fileSystem = new WindowsFileSystem(logManager.GetLogger("FileSystem"));
|
var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), true, true, true);
|
||||||
fileSystem.AddShortcutHandler(new LnkShortcutHandler());
|
|
||||||
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
|
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
|
||||||
|
|
||||||
var nativeApp = new WindowsApp(fileSystem, _logger)
|
var imageEncoder = new NullImageEncoder();
|
||||||
{
|
|
||||||
IsRunningAsService = runService
|
|
||||||
};
|
|
||||||
|
|
||||||
var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths);
|
_appHost = new CoreAppHost(appPaths,
|
||||||
|
|
||||||
_appHost = new ApplicationHost(appPaths,
|
|
||||||
logManager,
|
logManager,
|
||||||
options,
|
options,
|
||||||
fileSystem,
|
fileSystem,
|
||||||
nativeApp,
|
|
||||||
new PowerManagement(),
|
new PowerManagement(),
|
||||||
"emby.windows.zip",
|
"emby.windows.zip",
|
||||||
new EnvironmentInfo(),
|
new EnvironmentInfo(),
|
||||||
imageEncoder,
|
imageEncoder,
|
||||||
new Server.Startup.Common.SystemEvents(logManager.GetLogger("SystemEvents")),
|
new CoreSystemEvents(),
|
||||||
new RecyclableMemoryStreamProvider(),
|
new MemoryStreamFactory(),
|
||||||
new NetworkManager(logManager.GetLogger("NetworkManager")),
|
new NetworkManager(logManager.GetLogger("NetworkManager")),
|
||||||
GenerateCertificate,
|
GenerateCertificate,
|
||||||
() => Environment.UserDomainName);
|
() => "EmbyUser");
|
||||||
|
|
||||||
var initProgress = new Progress<double>();
|
var initProgress = new Progress<double>();
|
||||||
|
|
||||||
|
@ -275,12 +260,6 @@ namespace Emby.Server
|
||||||
{
|
{
|
||||||
Task.WaitAll(task);
|
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 = ApplicationTaskCompletionSource.Task;
|
||||||
Task.WaitAll(task);
|
Task.WaitAll(task);
|
||||||
}
|
}
|
||||||
|
@ -288,15 +267,7 @@ namespace Emby.Server
|
||||||
|
|
||||||
private static void GenerateCertificate(string certPath, string certHost)
|
private static void GenerateCertificate(string certPath, string certHost)
|
||||||
{
|
{
|
||||||
CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger);
|
//CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger);
|
||||||
}
|
|
||||||
|
|
||||||
static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.Reason == SessionSwitchReason.SessionLogon)
|
|
||||||
{
|
|
||||||
BrowserLauncher.OpenDashboard(_appHost);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -304,11 +275,6 @@ namespace Emby.Server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static void StartService(ILogManager logManager)
|
private static void StartService(ILogManager logManager)
|
||||||
{
|
{
|
||||||
var service = new BackgroundService(logManager.GetLogger("Service"));
|
|
||||||
|
|
||||||
service.Disposed += service_Disposed;
|
|
||||||
|
|
||||||
ServiceBase.Run(service);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -329,19 +295,6 @@ namespace Emby.Server
|
||||||
DisposeAppHost();
|
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>
|
/// <summary>
|
||||||
/// Handles the UnhandledException event of the CurrentDomain control.
|
/// Handles the UnhandledException event of the CurrentDomain control.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -355,7 +308,7 @@ namespace Emby.Server
|
||||||
|
|
||||||
if (!_isRunningAsService)
|
if (!_isRunningAsService)
|
||||||
{
|
{
|
||||||
MessageBox.Show("Unhandled exception: " + exception.Message);
|
ShowMessageBox("Unhandled exception: " + exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Debugger.IsAttached)
|
if (!Debugger.IsAttached)
|
||||||
|
@ -381,8 +334,8 @@ namespace Emby.Server
|
||||||
// Update is there - execute update
|
// Update is there - execute update
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty;
|
//var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty;
|
||||||
new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName);
|
//new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName);
|
||||||
|
|
||||||
// And just let the app exit so it can update
|
// And just let the app exit so it can update
|
||||||
return true;
|
return true;
|
||||||
|
@ -391,13 +344,18 @@ namespace Emby.Server
|
||||||
{
|
{
|
||||||
logger.ErrorException("Error starting updater.", e);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ShowMessageBox(string msg)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static void Shutdown()
|
public static void Shutdown()
|
||||||
{
|
{
|
||||||
if (_isRunningAsService)
|
if (_isRunningAsService)
|
||||||
|
@ -469,90 +427,6 @@ namespace Emby.Server
|
||||||
return false;
|
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>
|
/// <summary>
|
||||||
/// Sets the error mode.
|
/// Sets the error mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -11,7 +11,11 @@
|
||||||
"type": "platform",
|
"type": "platform",
|
||||||
"version": "1.0.1"
|
"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": {
|
"frameworks": {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user