diff --git a/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs b/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
index 887321a72..7643c93ae 100644
--- a/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
+++ b/src/Artemis.Core/Services/Interfaces/IPluginManagementService.cs
@@ -71,7 +71,7 @@ namespace Artemis.Core.Services
Plugin ImportPlugin(string fileName);
///
- /// Unloads and permanently removes the provided plugin
+ /// Unloads and permanently removes the provided plugin
///
/// The plugin to remove
void RemovePlugin(Plugin plugin);
@@ -127,6 +127,13 @@ namespace Artemis.Core.Services
///
DeviceProvider GetDeviceProviderByDevice(IRGBDevice device);
+ ///
+ /// Queues an action for the provided plugin for the next time Artemis starts, before plugins are loaded
+ ///
+ /// The plugin to queue the action for
+ /// The action to take
+ void QueuePluginAction(Plugin plugin, PluginManagementAction pluginAction);
+
#region Events
///
diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs
index 952c62c4f..cadb77caf 100644
--- a/src/Artemis.Core/Services/PluginManagementService.cs
+++ b/src/Artemis.Core/Services/PluginManagementService.cs
@@ -27,6 +27,7 @@ namespace Artemis.Core.Services
private readonly ILogger _logger;
private readonly IPluginRepository _pluginRepository;
private readonly List _plugins;
+ private bool _isElevated;
public PluginManagementService(IKernel kernel, ILogger logger, IPluginRepository pluginRepository)
{
@@ -34,6 +35,8 @@ namespace Artemis.Core.Services
_logger = logger;
_pluginRepository = pluginRepository;
_plugins = new List();
+
+ ProcessQueuedActions();
}
private void CopyBuiltInPlugin(FileInfo zipFileInfo, ZipArchive zipArchive)
@@ -181,6 +184,7 @@ namespace Artemis.Core.Services
if (LoadingPlugins)
throw new ArtemisCoreException("Cannot load plugins while a previous load hasn't been completed yet.");
+ _isElevated = isElevated;
LoadingPlugins = true;
// Unload all currently loaded plugins first
@@ -203,7 +207,7 @@ namespace Artemis.Core.Services
// ReSharper disable InconsistentlySynchronizedField - It's read-only, idc
_logger.Debug("Loaded {count} plugin(s)", _plugins.Count);
- bool adminRequired = _plugins.Any(p => p.Entity.IsEnabled && p.Info.RequiresAdmin);
+ bool adminRequired = _plugins.Any(p => p.Info.RequiresAdmin && p.Entity.IsEnabled && p.Entity.Features.Any(f => f.IsEnabled));
if (!isElevated && adminRequired)
{
_logger.Information("Restarting because one or more plugins requires elevation");
@@ -336,6 +340,19 @@ namespace Artemis.Core.Services
if (plugin.Assembly == null)
throw new ArtemisPluginException(plugin, "Cannot enable a plugin that hasn't successfully been loaded");
+ if (plugin.Info.RequiresAdmin && plugin.Entity.Features.Any(f => f.IsEnabled) && !_isElevated)
+ {
+ if (!saveState)
+ throw new ArtemisCoreException("Cannot enable a plugin that requires elevation without saving it's state.");
+
+ plugin.Entity.IsEnabled = true;
+ SavePlugin(plugin);
+
+ _logger.Information("Restarting because a newly enabled plugin requires elevation");
+ Utilities.Restart(true, TimeSpan.FromMilliseconds(500));
+ return;
+ }
+
// Create the Ninject child kernel and load the module
plugin.Kernel = new ChildKernel(_kernel, new PluginModule(plugin));
OnPluginEnabling(new PluginEventArgs(plugin));
@@ -523,6 +540,21 @@ namespace Artemis.Core.Services
_logger.Verbose("Enabling plugin feature {feature} - {plugin}", pluginFeature, pluginFeature.Plugin);
OnPluginFeatureEnabling(new PluginFeatureEventArgs(pluginFeature));
+
+ if (pluginFeature.Plugin.Info.RequiresAdmin && !_isElevated)
+ {
+ if (!saveState)
+ throw new ArtemisCoreException("Cannot enable a feature that requires elevation without saving it's state.");
+
+ pluginFeature.Entity.IsEnabled = true;
+ pluginFeature.Plugin.Entity.IsEnabled = true;
+ SavePlugin(pluginFeature.Plugin);
+
+ _logger.Information("Restarting because a newly enabled feature requires elevation");
+ Utilities.Restart(true, TimeSpan.FromMilliseconds(500));
+ return;
+ }
+
try
{
pluginFeature.SetEnabled(true, isAutoEnable);
@@ -586,6 +618,34 @@ namespace Artemis.Core.Services
#endregion
+ #region Queued actions
+
+ public void QueuePluginAction(Plugin plugin, PluginManagementAction pluginAction)
+ {
+ List existing = _pluginRepository.GetQueuedActions(plugin.Guid);
+ if (existing.Any(e => pluginAction == PluginManagementAction.Delete && e is PluginQueuedDeleteEntity))
+ return;
+
+ if (pluginAction == PluginManagementAction.Delete)
+ _pluginRepository.AddQueuedAction(new PluginQueuedDeleteEntity {PluginGuid = plugin.Guid, Directory = plugin.Directory.FullName});
+ }
+
+ private void ProcessQueuedActions()
+ {
+ foreach (PluginQueuedActionEntity pluginQueuedActionEntity in _pluginRepository.GetQueuedActions())
+ {
+ if (pluginQueuedActionEntity is PluginQueuedDeleteEntity deleteAction)
+ {
+ if (Directory.Exists(deleteAction.Directory))
+ Directory.Delete(deleteAction.Directory, true);
+ }
+
+ _pluginRepository.RemoveQueuedAction(pluginQueuedActionEntity);
+ }
+ }
+
+ #endregion
+
#region Storage
private void SavePlugin(Plugin plugin)
@@ -673,4 +733,20 @@ namespace Artemis.Core.Services
#endregion
}
+
+ ///
+ /// Represents a type of plugin management action
+ ///
+ public enum PluginManagementAction
+ {
+ ///
+ /// A plugin management action that removes a plugin
+ ///
+ Delete,
+
+ // ///
+ // /// A plugin management action that updates a plugin
+ // ///
+ // Update
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs b/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs
index ae4827426..08a17f922 100644
--- a/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs
+++ b/src/Artemis.Storage/Entities/Plugins/PluginSettingEntity.cs
@@ -13,4 +13,21 @@ namespace Artemis.Storage.Entities.Plugins
public string Name { get; set; }
public string Value { get; set; }
}
+
+ ///
+ /// Represents a queued action for a plugin
+ ///
+ public abstract class PluginQueuedActionEntity
+ {
+ public Guid Id { get; set; }
+ public Guid PluginGuid { get; set; }
+ }
+
+ ///
+ /// Represents a queued delete action for a plugin
+ ///
+ public class PluginQueuedDeleteEntity : PluginQueuedActionEntity
+ {
+ public string Directory { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs b/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
index 9a1258416..d93ba4628 100644
--- a/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
+++ b/src/Artemis.Storage/Repositories/Interfaces/IPluginRepository.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using Artemis.Storage.Entities.Plugins;
namespace Artemis.Storage.Repositories.Interfaces
@@ -8,9 +9,15 @@ namespace Artemis.Storage.Repositories.Interfaces
void AddPlugin(PluginEntity pluginEntity);
PluginEntity GetPluginByGuid(Guid pluginGuid);
void SavePlugin(PluginEntity pluginEntity);
+
void AddSetting(PluginSettingEntity pluginSettingEntity);
PluginSettingEntity GetSettingByGuid(Guid pluginGuid);
PluginSettingEntity GetSettingByNameAndGuid(string name, Guid pluginGuid);
void SaveSetting(PluginSettingEntity pluginSettingEntity);
+
+ void AddQueuedAction(PluginQueuedActionEntity pluginQueuedActionEntity);
+ List GetQueuedActions();
+ List GetQueuedActions(Guid pluginGuid);
+ void RemoveQueuedAction(PluginQueuedActionEntity pluginQueuedActionEntity);
}
}
\ No newline at end of file
diff --git a/src/Artemis.Storage/Repositories/PluginRepository.cs b/src/Artemis.Storage/Repositories/PluginRepository.cs
index b97c8fc83..5a923a60a 100644
--- a/src/Artemis.Storage/Repositories/PluginRepository.cs
+++ b/src/Artemis.Storage/Repositories/PluginRepository.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using Artemis.Storage.Entities.Plugins;
using Artemis.Storage.Repositories.Interfaces;
using LiteDB;
@@ -14,6 +15,7 @@ namespace Artemis.Storage.Repositories
_repository = repository;
_repository.Database.GetCollection().EnsureIndex(s => new {s.Name, s.PluginGuid}, true);
+ _repository.Database.GetCollection().EnsureIndex(s => s.PluginGuid);
}
public void AddPlugin(PluginEntity pluginEntity)
@@ -51,5 +53,24 @@ namespace Artemis.Storage.Repositories
{
_repository.Upsert(pluginSettingEntity);
}
+
+ public List GetQueuedActions()
+ {
+ return _repository.Query().ToList();
+ }
+
+ public List GetQueuedActions(Guid pluginGuid)
+ {
+ return _repository.Query().Where(q => q.PluginGuid == pluginGuid).ToList();
+ }
+
+ public void AddQueuedAction(PluginQueuedActionEntity pluginQueuedActionEntity)
+ {
+ _repository.Upsert(pluginQueuedActionEntity);
+ }
+ public void RemoveQueuedAction(PluginQueuedActionEntity pluginQueuedActionEntity)
+ {
+ _repository.Delete(pluginQueuedActionEntity.Id);
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
index 2d0190136..02d543a4c 100644
--- a/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
+++ b/src/Artemis.UI/Ninject/Factories/IVMFactory.cs
@@ -39,7 +39,7 @@ namespace Artemis.UI.Ninject.Factories
public interface ISettingsVmFactory : IVmFactory
{
PluginSettingsViewModel CreatePluginSettingsViewModel(Plugin plugin);
- PluginFeatureViewModel CreatePluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo);
+ PluginFeatureViewModel CreatePluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo, bool showShield);
DeviceSettingsViewModel CreateDeviceSettingsViewModel(ArtemisDevice device);
}
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
index c02ee2db3..86e8fdb7b 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Tabs/General/GeneralSettingsTabViewModel.cs
@@ -3,17 +3,20 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Reflection.Metadata;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Xml.Linq;
using Artemis.Core;
using Artemis.Core.LayerBrushes;
using Artemis.Core.Services;
+using Artemis.Core.Services.Core;
using Artemis.UI.Properties;
using Artemis.UI.Screens.StartupWizard;
using Artemis.UI.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
+using Artemis.UI.Utilities;
using Ninject;
using Serilog.Events;
using Stylet;
@@ -70,7 +73,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
_defaultLayerBrushDescriptor = _settingsService.GetSetting("ProfileEditor.DefaultLayerBrushDescriptor", new LayerBrushReference
{
LayerBrushProviderId = "Artemis.Plugins.LayerBrushes.Color.ColorBrushProvider-92a9d6ba",
- BrushType = "ColorBrush"
+ BrushType = "SolidBrush"
});
WebServerPortSetting = _settingsService.GetSetting("WebServer.Port", 9696);
@@ -306,7 +309,8 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
if (File.Exists(autoRunFile))
File.Delete(autoRunFile);
- // TODO: Don't do anything if running a development build, only auto-run release builds
+ if (Constants.BuildInfo.IsLocalBuild)
+ return;
// Create or remove the task if necessary
try
@@ -314,26 +318,13 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
bool taskCreated = false;
if (!recreate)
{
- Process schtasks = new()
- {
- StartInfo =
- {
- WindowStyle = ProcessWindowStyle.Hidden,
- UseShellExecute = true,
- FileName = Path.Combine(Environment.SystemDirectory, "schtasks.exe"),
- Arguments = "/TN \"Artemis 2 autorun\""
- }
- };
-
- schtasks.Start();
- schtasks.WaitForExit();
- taskCreated = schtasks.ExitCode == 0;
+ taskCreated = SettingsUtilities.IsAutoRunTaskCreated();
}
if (StartWithWindows && !taskCreated)
- CreateAutoRunTask();
+ SettingsUtilities.CreateAutoRunTask(TimeSpan.FromSeconds(AutoRunDelay));
else if (!StartWithWindows && taskCreated)
- RemoveAutoRunTask();
+ SettingsUtilities.RemoveAutoRunTask();
}
catch (Exception e)
{
@@ -341,71 +332,10 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
throw;
}
}
-
- private void CreateAutoRunTask()
- {
- XDocument document = XDocument.Parse(Resources.artemis_autorun);
- XElement task = document.Descendants().First();
-
- task.Descendants().First(d => d.Name.LocalName == "RegistrationInfo").Descendants().First(d => d.Name.LocalName == "Date")
- .SetValue(DateTime.Now);
- task.Descendants().First(d => d.Name.LocalName == "RegistrationInfo").Descendants().First(d => d.Name.LocalName == "Author")
- .SetValue(WindowsIdentity.GetCurrent().Name);
-
- task.Descendants().First(d => d.Name.LocalName == "Triggers").Descendants().First(d => d.Name.LocalName == "LogonTrigger").Descendants().First(d => d.Name.LocalName == "Delay")
- .SetValue(TimeSpan.FromSeconds(AutoRunDelay));
-
- task.Descendants().First(d => d.Name.LocalName == "Principals").Descendants().First(d => d.Name.LocalName == "Principal").Descendants().First(d => d.Name.LocalName == "UserId")
- .SetValue(WindowsIdentity.GetCurrent().User.Value);
-
- task.Descendants().First(d => d.Name.LocalName == "Actions").Descendants().First(d => d.Name.LocalName == "Exec").Descendants().First(d => d.Name.LocalName == "WorkingDirectory")
- .SetValue(Constants.ApplicationFolder);
- task.Descendants().First(d => d.Name.LocalName == "Actions").Descendants().First(d => d.Name.LocalName == "Exec").Descendants().First(d => d.Name.LocalName == "Command")
- .SetValue("\"" + Constants.ExecutablePath + "\"");
-
- string xmlPath = Path.GetTempFileName();
- using (Stream fileStream = new FileStream(xmlPath, FileMode.Create))
- {
- document.Save(fileStream);
- }
-
- Process schtasks = new()
- {
- StartInfo =
- {
- WindowStyle = ProcessWindowStyle.Hidden,
- UseShellExecute = true,
- Verb = "runas",
- FileName = Path.Combine(Environment.SystemDirectory, "schtasks.exe"),
- Arguments = $"/Create /XML \"{xmlPath}\" /tn \"Artemis 2 autorun\" /F"
- }
- };
-
- schtasks.Start();
- schtasks.WaitForExit();
-
- File.Delete(xmlPath);
- }
-
- private void RemoveAutoRunTask()
- {
- Process schtasks = new()
- {
- StartInfo =
- {
- WindowStyle = ProcessWindowStyle.Hidden,
- UseShellExecute = true,
- Verb = "runas",
- FileName = Path.Combine(Environment.SystemDirectory, "schtasks.exe"),
- Arguments = "/Delete /TN \"Artemis 2 autorun\" /f"
- }
- };
-
- schtasks.Start();
- schtasks.WaitForExit();
- }
}
+
+
public enum ApplicationColorScheme
{
Light,
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureView.xaml b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureView.xaml
index ad2358da7..b97f80323 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureView.xaml
@@ -45,8 +45,17 @@
-
+
+
Feature enabled
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureViewModel.cs
index f7a0899d1..fda530a9c 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginFeatureViewModel.cs
@@ -11,26 +11,33 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
{
public class PluginFeatureViewModel : Screen
{
+ private readonly ICoreService _coreService;
private readonly IDialogService _dialogService;
private readonly IPluginManagementService _pluginManagementService;
private bool _enabling;
private readonly IMessageService _messageService;
- public PluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo,
+ public PluginFeatureViewModel(PluginFeatureInfo pluginFeatureInfo,
+ bool showShield,
+ ICoreService coreService,
IDialogService dialogService,
IPluginManagementService pluginManagementService,
IMessageService messageService)
{
+ _coreService = coreService;
_dialogService = dialogService;
_pluginManagementService = pluginManagementService;
_messageService = messageService;
FeatureInfo = pluginFeatureInfo;
+ ShowShield = FeatureInfo.Plugin.Info.RequiresAdmin && showShield;
}
public PluginFeatureInfo FeatureInfo { get; }
public Exception LoadException => FeatureInfo.Instance?.LoadException;
+ public bool ShowShield { get; }
+
public bool Enabling
{
get => _enabling;
@@ -95,6 +102,16 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
try
{
+ if (FeatureInfo.Plugin.Info.RequiresAdmin && !_coreService.IsElevated)
+ {
+ bool confirmed = await _dialogService.ShowConfirmDialog("Enable feature", "The plugin of this feature requires admin rights, are you sure you want to enable it?");
+ if (!confirmed)
+ {
+ NotifyOfPropertyChange(nameof(IsEnabled));
+ return;
+ }
+ }
+
await Task.Run(() => _pluginManagementService.EnablePluginFeature(FeatureInfo.Instance, true));
}
catch (Exception e)
diff --git a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs
index 77cdc5d6d..19414cb33 100644
--- a/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Tabs/Plugins/PluginSettingsViewModel.cs
@@ -118,7 +118,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
protected override void OnInitialActivate()
{
foreach (PluginFeatureInfo pluginFeatureInfo in Plugin.Features)
- Items.Add(_settingsVmFactory.CreatePluginFeatureViewModel(pluginFeatureInfo));
+ Items.Add(_settingsVmFactory.CreatePluginFeatureViewModel(pluginFeatureInfo, false));
base.OnInitialActivate();
}
diff --git a/src/Artemis.UI/Screens/StartupWizard/StartupWizardView.xaml b/src/Artemis.UI/Screens/StartupWizard/StartupWizardView.xaml
index 0d959c213..b81bbab63 100644
--- a/src/Artemis.UI/Screens/StartupWizard/StartupWizardView.xaml
+++ b/src/Artemis.UI/Screens/StartupWizard/StartupWizardView.xaml
@@ -5,6 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mde="https://spiegelp.github.io/MaterialDesignExtensions/winfx/xaml"
xmlns:s="https://github.com/canton7/Stylet"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
mc:Ignorable="d"
Width="800"
Height="600"
@@ -17,47 +18,58 @@
FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
UseLayoutRounding="True"
d:DesignHeight="450" d:DesignWidth="800">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/StartupWizard/StartupWizardViewModel.cs b/src/Artemis.UI/Screens/StartupWizard/StartupWizardViewModel.cs
index 73d244cf1..8f1eb12a0 100644
--- a/src/Artemis.UI/Screens/StartupWizard/StartupWizardViewModel.cs
+++ b/src/Artemis.UI/Screens/StartupWizard/StartupWizardViewModel.cs
@@ -2,18 +2,22 @@
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Screens.StartupWizard.Steps;
+using Artemis.UI.Shared.Services;
using MaterialDesignExtensions.Controllers;
using MaterialDesignExtensions.Controls;
+using MaterialDesignThemes.Wpf;
using Stylet;
namespace Artemis.UI.Screens.StartupWizard
{
public class StartupWizardViewModel : Conductor.Collection.OneActive
{
+ private readonly IMessageService _messageService;
private readonly ISettingsService _settingsService;
private StepperController _stepperController;
public StartupWizardViewModel(ISettingsService settingsService,
+ IMessageService messageService,
WelcomeStepViewModel welcome,
DevicesStepViewModel devices,
LayoutStepViewModel layout,
@@ -21,6 +25,7 @@ namespace Artemis.UI.Screens.StartupWizard
FinishStepViewModel finish)
{
_settingsService = settingsService;
+ _messageService = messageService;
Items.Add(welcome);
Items.Add(devices);
Items.Add(layout);
@@ -30,6 +35,8 @@ namespace Artemis.UI.Screens.StartupWizard
ActiveItem = Items.First();
}
+ public ISnackbarMessageQueue MainMessageQueue { get; set; }
+
public void ActiveStepChanged(object sender, ActiveStepChangedEventArgs e)
{
Stepper stepper = (Stepper) sender;
@@ -40,22 +47,23 @@ namespace Artemis.UI.Screens.StartupWizard
}
public void SkipOrFinishWizard()
- {
- RequestClose();
- }
-
- protected override void OnClose()
{
PluginSetting setting = _settingsService.GetSetting("UI.SetupWizardCompleted", false);
setting.Value = true;
setting.Save();
- base.OnClose();
+ RequestClose();
}
-
+
public void Continue()
{
_stepperController.Continue();
}
+
+ protected override void OnInitialActivate()
+ {
+ MainMessageQueue = _messageService.MainMessageQueue;
+ base.OnInitialActivate();
+ }
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/StartupWizard/Steps/DevicesStepView.xaml b/src/Artemis.UI/Screens/StartupWizard/Steps/DevicesStepView.xaml
index df4f7c13f..bd9c7ddc2 100644
--- a/src/Artemis.UI/Screens/StartupWizard/Steps/DevicesStepView.xaml
+++ b/src/Artemis.UI/Screens/StartupWizard/Steps/DevicesStepView.xaml
@@ -16,7 +16,7 @@
- EnabledDevices are supported through the use of device providers.
+ Devices are supported through the use of device providers.
In the list below you can enable device providers for each brand you own by checking .
diff --git a/src/Artemis.UI/Screens/StartupWizard/Steps/DevicesStepViewModel.cs b/src/Artemis.UI/Screens/StartupWizard/Steps/DevicesStepViewModel.cs
index 16e677d38..efc7b29db 100644
--- a/src/Artemis.UI/Screens/StartupWizard/Steps/DevicesStepViewModel.cs
+++ b/src/Artemis.UI/Screens/StartupWizard/Steps/DevicesStepViewModel.cs
@@ -31,7 +31,7 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
IEnumerable features = _pluginManagementService.GetAllPlugins()
.SelectMany(p => p.Features.Where(f => typeof(DeviceProvider).IsAssignableFrom(f.FeatureType)))
.OrderBy(d => d.GetType().Name);
- Items.AddRange(features.Select(d => _settingsVmFactory.CreatePluginFeatureViewModel(d)));
+ Items.AddRange(features.Select(d => _settingsVmFactory.CreatePluginFeatureViewModel(d, true)));
base.OnActivate();
}
diff --git a/src/Artemis.UI/Screens/StartupWizard/Steps/SettingsStepViewModel.cs b/src/Artemis.UI/Screens/StartupWizard/Steps/SettingsStepViewModel.cs
index b1076408c..b1ed82ae8 100644
--- a/src/Artemis.UI/Screens/StartupWizard/Steps/SettingsStepViewModel.cs
+++ b/src/Artemis.UI/Screens/StartupWizard/Steps/SettingsStepViewModel.cs
@@ -7,6 +7,7 @@ using Artemis.UI.Screens.Settings.Tabs.General;
using Artemis.UI.Screens.Settings.Tabs.Plugins;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
+using Artemis.UI.Utilities;
using Stylet;
namespace Artemis.UI.Screens.StartupWizard.Steps
@@ -34,7 +35,7 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
_settingsService.GetSetting("UI.AutoRun", false).Value = value;
_settingsService.GetSetting("UI.AutoRun", false).Save();
NotifyOfPropertyChange(nameof(StartWithWindows));
- Task.Run(ApplyAutorun);
+ Task.Run(() => ApplyAutorun(false));
}
}
@@ -59,23 +60,35 @@ namespace Artemis.UI.Screens.StartupWizard.Steps
}
}
- private void ApplyAutorun()
+ private void ApplyAutorun(bool recreate)
{
+ if (!StartWithWindows)
+ StartMinimized = false;
+
+ // Remove the old auto-run method of placing a shortcut in shell:startup
+ string autoRunFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), "Artemis.lnk");
+ if (File.Exists(autoRunFile))
+ File.Delete(autoRunFile);
+
+ // Local builds shouldn't auto-run, this is just annoying
+ // if (Constants.BuildInfo.IsLocalBuild)
+ // return;
+
+ // Create or remove the task if necessary
try
{
- string autoRunFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), "Artemis.lnk");
- string executableFile = Constants.ExecutablePath;
+ bool taskCreated = false;
+ if (!recreate)
+ taskCreated = SettingsUtilities.IsAutoRunTaskCreated();
- if (File.Exists(autoRunFile))
- File.Delete(autoRunFile);
- if (StartWithWindows)
- ShortcutUtilities.Create(autoRunFile, executableFile, "--autorun", new FileInfo(executableFile).DirectoryName, "Artemis", "", "");
- else
- StartMinimized = false;
+ if (StartWithWindows && !taskCreated)
+ SettingsUtilities.CreateAutoRunTask(TimeSpan.FromSeconds(15));
+ else if (!StartWithWindows && taskCreated)
+ SettingsUtilities.RemoveAutoRunTask();
}
catch (Exception e)
{
- _dialogService.ShowExceptionDialog("An exception occured while trying to apply the auto run setting", e);
+ Execute.PostToUIThread(() => _dialogService.ShowExceptionDialog("An exception occured while trying to apply the auto run setting", e));
throw;
}
}
diff --git a/src/Artemis.UI/Utilities/SettingsUtilities.cs b/src/Artemis.UI/Utilities/SettingsUtilities.cs
new file mode 100644
index 000000000..44b43a395
--- /dev/null
+++ b/src/Artemis.UI/Utilities/SettingsUtilities.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Security.Principal;
+using System.Xml.Linq;
+using Artemis.Core;
+using Artemis.UI.Properties;
+
+namespace Artemis.UI.Utilities
+{
+ public static class SettingsUtilities
+ {
+ public static bool IsAutoRunTaskCreated()
+ {
+ Process schtasks = new()
+ {
+ StartInfo =
+ {
+ WindowStyle = ProcessWindowStyle.Hidden,
+ UseShellExecute = true,
+ FileName = Path.Combine(Environment.SystemDirectory, "schtasks.exe"),
+ Arguments = "/TN \"Artemis 2 autorun\""
+ }
+ };
+
+ schtasks.Start();
+ schtasks.WaitForExit();
+ return schtasks.ExitCode == 0;
+ }
+
+ public static void CreateAutoRunTask(TimeSpan autoRunDelay)
+ {
+ XDocument document = XDocument.Parse(Resources.artemis_autorun);
+ XElement task = document.Descendants().First();
+
+ task.Descendants().First(d => d.Name.LocalName == "RegistrationInfo").Descendants().First(d => d.Name.LocalName == "Date")
+ .SetValue(DateTime.Now);
+ task.Descendants().First(d => d.Name.LocalName == "RegistrationInfo").Descendants().First(d => d.Name.LocalName == "Author")
+ .SetValue(WindowsIdentity.GetCurrent().Name);
+
+ task.Descendants().First(d => d.Name.LocalName == "Triggers").Descendants().First(d => d.Name.LocalName == "LogonTrigger").Descendants().First(d => d.Name.LocalName == "Delay")
+ .SetValue(autoRunDelay);
+
+ task.Descendants().First(d => d.Name.LocalName == "Principals").Descendants().First(d => d.Name.LocalName == "Principal").Descendants().First(d => d.Name.LocalName == "UserId")
+ .SetValue(WindowsIdentity.GetCurrent().User.Value);
+
+ task.Descendants().First(d => d.Name.LocalName == "Actions").Descendants().First(d => d.Name.LocalName == "Exec").Descendants().First(d => d.Name.LocalName == "WorkingDirectory")
+ .SetValue(Constants.ApplicationFolder);
+ task.Descendants().First(d => d.Name.LocalName == "Actions").Descendants().First(d => d.Name.LocalName == "Exec").Descendants().First(d => d.Name.LocalName == "Command")
+ .SetValue("\"" + Constants.ExecutablePath + "\"");
+
+ string xmlPath = Path.GetTempFileName();
+ using (Stream fileStream = new FileStream(xmlPath, FileMode.Create))
+ {
+ document.Save(fileStream);
+ }
+
+ Process schtasks = new()
+ {
+ StartInfo =
+ {
+ WindowStyle = ProcessWindowStyle.Hidden,
+ UseShellExecute = true,
+ Verb = "runas",
+ FileName = Path.Combine(Environment.SystemDirectory, "schtasks.exe"),
+ Arguments = $"/Create /XML \"{xmlPath}\" /tn \"Artemis 2 autorun\" /F"
+ }
+ };
+
+ schtasks.Start();
+ schtasks.WaitForExit();
+
+ File.Delete(xmlPath);
+ }
+
+ public static void RemoveAutoRunTask()
+ {
+ Process schtasks = new()
+ {
+ StartInfo =
+ {
+ WindowStyle = ProcessWindowStyle.Hidden,
+ UseShellExecute = true,
+ Verb = "runas",
+ FileName = Path.Combine(Environment.SystemDirectory, "schtasks.exe"),
+ Arguments = "/Delete /TN \"Artemis 2 autorun\" /f"
+ }
+ };
+
+ schtasks.Start();
+ schtasks.WaitForExit();
+ }
+ }
+}
\ No newline at end of file