mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Plugins - Added RequiresAdmin boolean
Utilities - Simplified shutdown method signature Utilities - Added restart method with option to elevate Core - Moved actual shutdown/restart logic to UI
This commit is contained in:
parent
281c18200a
commit
de5b8e4458
26
src/Artemis.Core/Events/RestartEventArgs.cs
Normal file
26
src/Artemis.Core/Events/RestartEventArgs.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Artemis.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data about application restart events
|
||||||
|
/// </summary>
|
||||||
|
public class RestartEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
internal RestartEventArgs(bool elevate, TimeSpan delay)
|
||||||
|
{
|
||||||
|
Elevate = elevate;
|
||||||
|
Delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether the application should be restarted with elevated permissions
|
||||||
|
/// </summary>
|
||||||
|
public bool Elevate { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the delay before killing process and restarting
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan Delay { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,6 +17,7 @@ namespace Artemis.Core
|
|||||||
private string _main = null!;
|
private string _main = null!;
|
||||||
private string _name = null!;
|
private string _name = null!;
|
||||||
private Plugin _plugin = null!;
|
private Plugin _plugin = null!;
|
||||||
|
private bool _requiresAdmin;
|
||||||
private Version _version = null!;
|
private Version _version = null!;
|
||||||
|
|
||||||
internal PluginInfo()
|
internal PluginInfo()
|
||||||
@ -86,7 +87,8 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a boolean indicating whether this plugin should automatically enable all its features when it is first loaded
|
/// Gets or sets a boolean indicating whether this plugin should automatically enable all its features when it is first
|
||||||
|
/// loaded
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DefaultValue(true)]
|
[DefaultValue(true)]
|
||||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
|
||||||
@ -96,6 +98,16 @@ namespace Artemis.Core
|
|||||||
set => SetAndNotify(ref _autoEnableFeatures, value);
|
set => SetAndNotify(ref _autoEnableFeatures, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether this plugin requires elevated admin privileges
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty]
|
||||||
|
public bool RequiresAdmin
|
||||||
|
{
|
||||||
|
get => _requiresAdmin;
|
||||||
|
internal set => SetAndNotify(ref _requiresAdmin, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the plugin this info is associated with
|
/// Gets the plugin this info is associated with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -78,6 +78,7 @@ namespace Artemis.Core.Services
|
|||||||
public TimeSpan FrameTime { get; private set; }
|
public TimeSpan FrameTime { get; private set; }
|
||||||
public bool ModuleRenderingDisabled { get; set; }
|
public bool ModuleRenderingDisabled { get; set; }
|
||||||
public List<string>? StartupArguments { get; set; }
|
public List<string>? StartupArguments { get; set; }
|
||||||
|
public bool IsElevated { get; set; }
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
@ -93,18 +94,27 @@ namespace Artemis.Core.Services
|
|||||||
throw new ArtemisCoreException("Cannot initialize the core as it is already initialized.");
|
throw new ArtemisCoreException("Cannot initialize the core as it is already initialized.");
|
||||||
|
|
||||||
AssemblyInformationalVersionAttribute? versionAttribute = typeof(CoreService).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
|
AssemblyInformationalVersionAttribute? versionAttribute = typeof(CoreService).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
|
||||||
_logger.Information("Initializing Artemis Core version {version}, build {buildNumber} branch {branch}.", versionAttribute?.InformationalVersion, Constants.BuildInfo.BuildNumber,
|
_logger.Information(
|
||||||
Constants.BuildInfo.SourceBranch);
|
"Initializing Artemis Core version {version}, build {buildNumber} branch {branch}.",
|
||||||
// This should prevent a certain someone from removing HidSharp as an unused dependency as well
|
versionAttribute?.InformationalVersion,
|
||||||
_logger.Information("Forcing plugins to use HidSharp {hidSharpVersion}", Assembly.GetAssembly(typeof(HidDevice))!.GetName().Version);
|
Constants.BuildInfo.BuildNumber,
|
||||||
|
Constants.BuildInfo.SourceBranch
|
||||||
|
);
|
||||||
|
_logger.Information("Startup arguments: {args}", StartupArguments);
|
||||||
|
_logger.Information("Elevated permissions: {perms}", IsElevated);
|
||||||
|
|
||||||
ApplyLoggingLevel();
|
ApplyLoggingLevel();
|
||||||
|
|
||||||
|
// Don't remove even if it looks useless
|
||||||
|
// Just this line should prevent a certain someone from removing HidSharp as an unused dependency as well
|
||||||
|
Version? hidSharpVersion = Assembly.GetAssembly(typeof(HidDevice))!.GetName().Version;
|
||||||
|
_logger.Debug("Forcing plugins to use HidSharp {hidSharpVersion}", hidSharpVersion);
|
||||||
|
|
||||||
DeserializationLogger.Initialize(Kernel);
|
DeserializationLogger.Initialize(Kernel);
|
||||||
|
|
||||||
// Initialize the services
|
// Initialize the services
|
||||||
_pluginManagementService.CopyBuiltInPlugins();
|
_pluginManagementService.CopyBuiltInPlugins();
|
||||||
_pluginManagementService.LoadPlugins(StartupArguments != null && StartupArguments.Contains("--ignore-plugin-lock"));
|
_pluginManagementService.LoadPlugins(StartupArguments != null && StartupArguments.Contains("--ignore-plugin-lock"), IsElevated);
|
||||||
|
|
||||||
ArtemisSurface surfaceConfig = _surfaceService.ActiveSurface;
|
ArtemisSurface surfaceConfig = _surfaceService.ActiveSurface;
|
||||||
_logger.Information("Initialized with active surface entity {surfaceConfig}-{guid}", surfaceConfig.Name, surfaceConfig.EntityId);
|
_logger.Information("Initialized with active surface entity {surfaceConfig}-{guid}", surfaceConfig.Name, surfaceConfig.EntityId);
|
||||||
|
|||||||
@ -28,6 +28,11 @@ namespace Artemis.Core.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
List<string>? StartupArguments { get; set; }
|
List<string>? StartupArguments { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether Artemis is running in an elevated environment (admin permissions)
|
||||||
|
/// </summary>
|
||||||
|
bool IsElevated { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the core, only call once
|
/// Initializes the core, only call once
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -26,7 +26,7 @@ namespace Artemis.Core.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads all installed plugins. If plugins already loaded this will reload them all
|
/// Loads all installed plugins. If plugins already loaded this will reload them all
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void LoadPlugins(bool ignorePluginLock);
|
void LoadPlugins(bool ignorePluginLock, bool isElevated);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unloads all installed plugins.
|
/// Unloads all installed plugins.
|
||||||
|
|||||||
@ -172,7 +172,7 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
#region Plugins
|
#region Plugins
|
||||||
|
|
||||||
public void LoadPlugins(bool ignorePluginLock)
|
public void LoadPlugins(bool ignorePluginLock, bool isElevated)
|
||||||
{
|
{
|
||||||
if (LoadingPlugins)
|
if (LoadingPlugins)
|
||||||
throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet.");
|
throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet.");
|
||||||
@ -188,9 +188,7 @@ namespace Artemis.Core.Services
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Plugin plugin = LoadPlugin(subDirectory);
|
LoadPlugin(subDirectory);
|
||||||
if (plugin.Entity.IsEnabled)
|
|
||||||
EnablePlugin(plugin, false, ignorePluginLock);
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -198,6 +196,25 @@ namespace Artemis.Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lock (_plugins)
|
||||||
|
{
|
||||||
|
_logger.Debug("Loaded {count} plugin(s)", _plugins.Count);
|
||||||
|
|
||||||
|
bool mustElevate = !isElevated && _plugins.Any(p => p.Entity.IsEnabled && p.Info.RequiresAdmin);
|
||||||
|
if (mustElevate)
|
||||||
|
{
|
||||||
|
_logger.Information("Restarting because one or more plugins requires elevation");
|
||||||
|
// No need for a delay this early on, nothing that needs graceful shutdown is happening yet
|
||||||
|
Utilities.Restart(true, TimeSpan.Zero);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Plugin plugin in _plugins.Where(p => p.Entity.IsEnabled))
|
||||||
|
EnablePlugin(plugin, false, ignorePluginLock);
|
||||||
|
|
||||||
|
_logger.Debug("Enabled {count} plugin(s)", _plugins.Where(p => p.IsEnabled).Sum(p => p.Features.Count(f => f.IsEnabled)));
|
||||||
|
}
|
||||||
|
|
||||||
LoadingPlugins = false;
|
LoadingPlugins = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +234,7 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
public Plugin LoadPlugin(DirectoryInfo directory)
|
public Plugin LoadPlugin(DirectoryInfo directory)
|
||||||
{
|
{
|
||||||
_logger.Debug("Loading plugin from {directory}", directory.FullName);
|
_logger.Verbose("Loading plugin from {directory}", directory.FullName);
|
||||||
|
|
||||||
// Load the metadata
|
// Load the metadata
|
||||||
string metadataFile = Path.Combine(directory.FullName, "plugin.json");
|
string metadataFile = Path.Combine(directory.FullName, "plugin.json");
|
||||||
@ -411,8 +428,7 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
public void EnablePluginFeature(PluginFeature pluginFeature, bool saveState, bool isAutoEnable)
|
public void EnablePluginFeature(PluginFeature pluginFeature, bool saveState, bool isAutoEnable)
|
||||||
{
|
{
|
||||||
_logger.Debug("Enabling plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
_logger.Verbose("Enabling plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
||||||
|
|
||||||
|
|
||||||
OnPluginFeatureEnabling(new PluginFeatureEventArgs(pluginFeature));
|
OnPluginFeatureEnabling(new PluginFeatureEventArgs(pluginFeature));
|
||||||
try
|
try
|
||||||
@ -443,7 +459,7 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
if (pluginFeature.IsEnabled)
|
if (pluginFeature.IsEnabled)
|
||||||
{
|
{
|
||||||
_logger.Debug("Successfully enabled plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
_logger.Verbose("Successfully enabled plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
||||||
OnPluginFeatureEnabled(new PluginFeatureEventArgs(pluginFeature));
|
OnPluginFeatureEnabled(new PluginFeatureEventArgs(pluginFeature));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -457,7 +473,7 @@ namespace Artemis.Core.Services
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logger.Debug("Disabling plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
_logger.Verbose("Disabling plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
||||||
pluginFeature.SetEnabled(false);
|
pluginFeature.SetEnabled(false);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -470,7 +486,7 @@ namespace Artemis.Core.Services
|
|||||||
|
|
||||||
if (!pluginFeature.IsEnabled)
|
if (!pluginFeature.IsEnabled)
|
||||||
{
|
{
|
||||||
_logger.Debug("Successfully disabled plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
_logger.Verbose("Successfully disabled plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
|
||||||
OnPluginFeatureDisabled(new PluginFeatureEventArgs(pluginFeature));
|
OnPluginFeatureDisabled(new PluginFeatureEventArgs(pluginFeature));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Security.AccessControl;
|
using System.Security.AccessControl;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
|
|
||||||
@ -27,31 +28,22 @@ namespace Artemis.Core
|
|||||||
/// gracefully shut down
|
/// gracefully shut down
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="delay">The delay in seconds after which to kill the application (ignored when a debugger is attached)</param>
|
public static void Shutdown()
|
||||||
/// <param name="restart">Whether or not to restart the application after shutdown (ignored when a debugger is attached)</param>
|
|
||||||
public static void Shutdown(int delay, bool restart)
|
|
||||||
{
|
{
|
||||||
// Always kill the process after the delay has passed, with all the plugins a graceful shutdown cannot be guaranteed
|
|
||||||
string arguments = "-Command \"& {Start-Sleep -s " + delay + "; (Get-Process 'Artemis.UI').kill()}";
|
|
||||||
// If restart is required, start the executable again after the process was killed
|
|
||||||
if (restart)
|
|
||||||
arguments = "-Command \"& {Start-Sleep -s " + delay + "; (Get-Process 'Artemis.UI').kill(); Start-Process -FilePath '" + Process.GetCurrentProcess().MainModule!.FileName + "'}\"";
|
|
||||||
|
|
||||||
ProcessStartInfo info = new()
|
|
||||||
{
|
|
||||||
Arguments = arguments,
|
|
||||||
WindowStyle = ProcessWindowStyle.Hidden,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
FileName = "PowerShell.exe"
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!Debugger.IsAttached)
|
|
||||||
Process.Start(info);
|
|
||||||
|
|
||||||
// Request a graceful shutdown, whatever UI we're running can pick this up
|
// Request a graceful shutdown, whatever UI we're running can pick this up
|
||||||
OnShutdownRequested();
|
OnShutdownRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restarts the application
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elevate">Whether the application should be restarted with elevated permissions</param>
|
||||||
|
/// <param name="delay">Delay in seconds before killing process and restarting </param>
|
||||||
|
public static void Restart(bool elevate, TimeSpan delay)
|
||||||
|
{
|
||||||
|
OnRestartRequested(new RestartEventArgs(elevate, delay));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the provided URL in the default web browser
|
/// Opens the provided URL in the default web browser
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -105,11 +97,21 @@ namespace Artemis.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static event EventHandler? ShutdownRequested;
|
public static event EventHandler? ShutdownRequested;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when the core has requested an application restart
|
||||||
|
/// </summary>
|
||||||
|
public static event EventHandler<RestartEventArgs>? RestartRequested;
|
||||||
|
|
||||||
private static void OnShutdownRequested()
|
private static void OnShutdownRequested()
|
||||||
{
|
{
|
||||||
ShutdownRequested?.Invoke(null, EventArgs.Empty);
|
ShutdownRequested?.Invoke(null, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private static void OnRestartRequested(RestartEventArgs e)
|
||||||
|
{
|
||||||
|
RestartRequested?.Invoke(null, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,11 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Markup;
|
using System.Windows.Markup;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
using Artemis.Core;
|
||||||
using Artemis.Core.Ninject;
|
using Artemis.Core.Ninject;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Ninject;
|
using Artemis.UI.Ninject;
|
||||||
@ -37,6 +40,7 @@ namespace Artemis.UI
|
|||||||
protected override void Launch()
|
protected override void Launch()
|
||||||
{
|
{
|
||||||
Core.Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
|
Core.Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
|
||||||
|
Core.Utilities.RestartRequested += UtilitiesOnRestartRequested;
|
||||||
Core.Utilities.PrepareFirstLaunch();
|
Core.Utilities.PrepareFirstLaunch();
|
||||||
|
|
||||||
ILogger logger = Kernel.Get<ILogger>();
|
ILogger logger = Kernel.Get<ILogger>();
|
||||||
@ -77,6 +81,7 @@ namespace Artemis.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
_core.StartupArguments = StartupArguments;
|
_core.StartupArguments = StartupArguments;
|
||||||
|
_core.IsElevated = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
|
||||||
_core.Initialize();
|
_core.Initialize();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@ -124,6 +129,30 @@ namespace Artemis.UI
|
|||||||
|
|
||||||
private void UtilitiesOnShutdownRequested(object sender, EventArgs e)
|
private void UtilitiesOnShutdownRequested(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
// Use PowerShell to kill the process after 2 sec just in case
|
||||||
|
ProcessStartInfo info = new()
|
||||||
|
{
|
||||||
|
Arguments = "-Command \"& {Start-Sleep -s 2; (Get-Process 'Artemis.UI').kill()}",
|
||||||
|
WindowStyle = ProcessWindowStyle.Hidden,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
FileName = "PowerShell.exe"
|
||||||
|
};
|
||||||
|
Process.Start(info);
|
||||||
|
|
||||||
|
Execute.OnUIThread(() => Application.Current.Shutdown());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UtilitiesOnRestartRequested(object sender, RestartEventArgs e)
|
||||||
|
{
|
||||||
|
ProcessStartInfo info = new()
|
||||||
|
{
|
||||||
|
Arguments =
|
||||||
|
$"-Command \"& {{Start-Sleep -Milliseconds {(int) e.Delay.TotalMilliseconds}; (Get-Process 'Artemis.UI').kill(); Start-Process -FilePath '{Constants.ExecutablePath}' {(e.Elevate ? "-Verb RunAs" : "")}}}\"",
|
||||||
|
WindowStyle = ProcessWindowStyle.Hidden,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
FileName = "PowerShell.exe"
|
||||||
|
};
|
||||||
|
Process.Start(info);
|
||||||
Execute.OnUIThread(() => Application.Current.Shutdown());
|
Execute.OnUIThread(() => Application.Current.Shutdown());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,8 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Button>
|
</Button>
|
||||||
<Button Content="Force garbage collection" Command="{s:Action ForceGarbageCollection}" />
|
<Button Content="Force garbage collection" Command="{s:Action ForceGarbageCollection}" />
|
||||||
|
<Button Content="Elevate permissions" Command="{s:Action Elevate}" />
|
||||||
|
<Button Content="Restart" Command="{s:Action Restart}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</materialDesign:PopupBox>
|
</materialDesign:PopupBox>
|
||||||
</mde:AppBar>
|
</mde:AppBar>
|
||||||
|
|||||||
@ -43,5 +43,15 @@ namespace Artemis.UI.Screens.Settings.Debug
|
|||||||
GC.WaitForPendingFinalizers();
|
GC.WaitForPendingFinalizers();
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Elevate()
|
||||||
|
{
|
||||||
|
Core.Utilities.Restart(true, TimeSpan.FromMilliseconds(500));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Restart()
|
||||||
|
{
|
||||||
|
Core.Utilities.Restart(false, TimeSpan.FromMilliseconds(500));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ namespace Artemis.UI.Screens
|
|||||||
|
|
||||||
public void TrayExit()
|
public void TrayExit()
|
||||||
{
|
{
|
||||||
Core.Utilities.Shutdown(2, false);
|
Core.Utilities.Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TrayOpenDebugger()
|
public void TrayOpenDebugger()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user