diff --git a/SPTInstaller/App.axaml.cs b/SPTInstaller/App.axaml.cs
index cc8165c..ea4dca0 100644
--- a/SPTInstaller/App.axaml.cs
+++ b/SPTInstaller/App.axaml.cs
@@ -4,26 +4,25 @@ using Avalonia.Markup.Xaml;
 using SPTInstaller.ViewModels;
 using SPTInstaller.Views;
 
-namespace SPTInstaller
+namespace SPTInstaller;
+
+public partial class App : Application
 {
-    public partial class App : Application
+    public override void Initialize()
     {
-        public override void Initialize()
-        {
-            AvaloniaXamlLoader.Load(this);
-        }
+        AvaloniaXamlLoader.Load(this);
+    }
 
-        public override void OnFrameworkInitializationCompleted()
+    public override void OnFrameworkInitializationCompleted()
+    {
+        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
         {
-            if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            desktop.MainWindow = new MainWindow
             {
-                desktop.MainWindow = new MainWindow
-                {
-                    DataContext = new MainWindowViewModel(),
-                };
-            }
-
-            base.OnFrameworkInitializationCompleted();
+                DataContext = new MainWindowViewModel(),
+            };
         }
+
+        base.OnFrameworkInitializationCompleted();
     }
 }
\ No newline at end of file
diff --git a/SPTInstaller/Behaviors/SpanBehavior.cs b/SPTInstaller/Behaviors/SpanBehavior.cs
index 6c009fa..db56f13 100644
--- a/SPTInstaller/Behaviors/SpanBehavior.cs
+++ b/SPTInstaller/Behaviors/SpanBehavior.cs
@@ -1,20 +1,19 @@
 using Avalonia;
 using Avalonia.Interactivity;
 
-namespace SPTInstaller.Behaviors
+namespace SPTInstaller.Behaviors;
+
+public class SpanBehavior : AvaloniaObject
 {
-    public class SpanBehavior : AvaloniaObject
+    public static readonly AttachedProperty<bool> SpanProperty = AvaloniaProperty.RegisterAttached<SpanBehavior, Interactive, bool>("Span");
+
+    public static void SetSpan(AvaloniaObject element, bool value)
     {
-        public static readonly AttachedProperty<bool> SpanProperty = AvaloniaProperty.RegisterAttached<SpanBehavior, Interactive, bool>("Span");
-
-        public static void SetSpan(AvaloniaObject element, bool value)
-        {
-            element.SetValue(SpanProperty, value);
-        }
-
-        public static bool GetSpan(AvaloniaObject element)
-        {
-            return element.GetValue(SpanProperty);
-        }
+        element.SetValue(SpanProperty, value);
     }
-}
+
+    public static bool GetSpan(AvaloniaObject element)
+    {
+        return element.GetValue(SpanProperty);
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Controllers/InstallController.cs b/SPTInstaller/Controllers/InstallController.cs
index 9669b42..bc7056f 100644
--- a/SPTInstaller/Controllers/InstallController.cs
+++ b/SPTInstaller/Controllers/InstallController.cs
@@ -2,67 +2,65 @@
 using SharpCompress;
 using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
-using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Threading.Tasks;
 
-namespace SPTInstaller.Controllers
+namespace SPTInstaller.Controllers;
+
+public class InstallController
 {
-    public class InstallController
+    public event EventHandler<IProgressableTask> TaskChanged = delegate { };
+
+    private IPreCheck[] _preChecks { get; set; }
+    private IProgressableTask[] _tasks { get; set; }
+
+    public InstallController(IProgressableTask[] tasks, IPreCheck[] preChecks = null)
     {
-        public event EventHandler<IProgressableTask> TaskChanged = delegate { };
-
-        private IPreCheck[] _preChecks { get; set; }
-        private IProgressableTask[] _tasks { get; set; }
-
-        public InstallController(IProgressableTask[] tasks, IPreCheck[] preChecks = null)
-        {
-            _tasks = tasks;
-            _preChecks = preChecks;
-        }
-
-        public async Task<IResult> RunPreChecks()
-        {
-            Log.Information("-<>--<>- Running PreChecks -<>--<>-");
-            var requiredResults = new List<IResult>();
-
-            _preChecks.ForEach(x => x.IsPending = true);
-
-            foreach (var check in _preChecks)
-            {
-                var result = await check.RunCheck();
-
-                Log.Information($"PreCheck: {check.Name} ({(check.IsRequired ? "Required" : "Optional")}) -> {(result.Succeeded ? "Passed" : "Failed")}");
-
-                if (check.IsRequired)
-                {
-                    requiredResults.Add(result);
-                }
-            }
-
-            foreach(var result in requiredResults)
-            {
-                if (!result.Succeeded)
-                    return Result.FromError("Some required checks have failed");
-            }
-
-            return Result.FromSuccess();
-        }
-
-        public async Task<IResult> RunTasks()
-        {
-            Log.Information("-<>--<>- Running Installer Tasks -<>--<>-");
-
-            foreach (var task in _tasks)
-            {
-                TaskChanged?.Invoke(null, task);
-
-                var result = await task.RunAsync();
-
-                if (!result.Succeeded) return result;
-            }
-
-            return Result.FromSuccess("Install Complete. Happy Playing!");
-        }
+        _tasks = tasks;
+        _preChecks = preChecks;
     }
-}
+
+    public async Task<IResult> RunPreChecks()
+    {
+        Log.Information("-<>--<>- Running PreChecks -<>--<>-");
+        var requiredResults = new List<IResult>();
+
+        _preChecks.ForEach(x => x.IsPending = true);
+
+        foreach (var check in _preChecks)
+        {
+            var result = await check.RunCheck();
+
+            Log.Information($"PreCheck: {check.Name} ({(check.IsRequired ? "Required" : "Optional")}) -> {(result.Succeeded ? "Passed" : "Failed")}");
+            
+            if (check.IsRequired)
+            {
+                requiredResults.Add(result);
+            }
+        }
+
+        if (requiredResults.Any(result => !result.Succeeded))
+        {
+            return Result.FromError("Some required checks have failed");
+        }
+
+        return Result.FromSuccess();
+    }
+
+    public async Task<IResult> RunTasks()
+    {
+        Log.Information("-<>--<>- Running Installer Tasks -<>--<>-");
+
+        foreach (var task in _tasks)
+        {
+            TaskChanged?.Invoke(null, task);
+
+            var result = await task.RunAsync();
+
+            if (!result.Succeeded) return result;
+        }
+
+        return Result.FromSuccess("Install Complete. Happy Playing!");
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Converters/InvertedProgressConverter.cs b/SPTInstaller/Converters/InvertedProgressConverter.cs
index 24d94a7..5ee62d8 100644
--- a/SPTInstaller/Converters/InvertedProgressConverter.cs
+++ b/SPTInstaller/Converters/InvertedProgressConverter.cs
@@ -1,29 +1,27 @@
 using Avalonia.Data.Converters;
-using System;
 using System.Globalization;
 
-namespace SPTInstaller.Converters
+namespace SPTInstaller.Converters;
+
+public class InvertedProgressConverter : IValueConverter
 {
-    public class InvertedProgressConverter : IValueConverter
+    public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
     {
-        public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+        if( value is int progress)
         {
-            if( value is int progress)
-            {
-                return 100 - progress;
-            }
-
-            return value;
+            return 100 - progress;
         }
 
-        public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
-        {
-            if ( value is int invertedProgress)
-            {
-                return 100 - invertedProgress;
-            }
-
-            return value;
-        }
+        return value;
     }
-}
+
+    public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+    {
+        if ( value is int invertedProgress)
+        {
+            return 100 - invertedProgress;
+        }
+
+        return value;
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/CustomControls/DistributedSpacePanel.cs b/SPTInstaller/CustomControls/DistributedSpacePanel.cs
index 783c0a4..e5a847b 100644
--- a/SPTInstaller/CustomControls/DistributedSpacePanel.cs
+++ b/SPTInstaller/CustomControls/DistributedSpacePanel.cs
@@ -1,77 +1,75 @@
 using Avalonia;
 using Avalonia.Controls;
 using SPTInstaller.Behaviors;
-using System;
 using System.Linq;
 
-namespace SPTInstaller.CustomControls
+namespace SPTInstaller.CustomControls;
+
+public class DistributedSpacePanel : Panel
 {
-    public class DistributedSpacePanel : Panel
+    protected override Size MeasureOverride(Size availableSize)
     {
-        protected override Size MeasureOverride(Size availableSize)
+        var children = Children;
+
+        for (int i = 0; i < children.Count; i++)
         {
-            var children = Children;
-
-            for (int i = 0; i < children.Count; i++)
-            {
-                // measure child objects so we can use their desired size in the arrange override
-                var child = children[i];
-                child.Measure(availableSize);
-            }
-
-            // we want to use all available space
-            return availableSize;
+            // measure child objects so we can use their desired size in the arrange override
+            var child = children[i];
+            child.Measure(availableSize);
         }
 
-        protected override Size ArrangeOverride(Size finalSize)
+        // we want to use all available space
+        return availableSize;
+    }
+
+    protected override Size ArrangeOverride(Size finalSize)
+    {
+        var children = Children;
+        Rect rcChild = new Rect(finalSize);
+        double previousChildSize = 0.0;
+
+        // get child objects that don't want to span the entire control
+        var nonSpanningChildren = children.Where(x => x.GetValue(SpanBehavior.SpanProperty) == false).ToList();
+
+        // get the total height off all non-spanning child objects
+        var totalChildHeight = nonSpanningChildren.Select(x => x.DesiredSize.Height).Sum();
+
+        // remove the total child height from our controls final size and divide it by the total non-spanning child objects
+        // except the last one, since it needs no space after it
+        var spacing = (finalSize.Height - totalChildHeight) / (nonSpanningChildren.Count - 1);
+
+        for (int i = 0; i < children.Count; i++)
         {
-            var children = Children;
-            Rect rcChild = new Rect(finalSize);
-            double previousChildSize = 0.0;
+            var child = children[i];
 
-            // get child objects that don't want to span the entire control
-            var nonSpanningChildren = children.Where(x => x.GetValue(SpanBehavior.SpanProperty) == false).ToList();
+            var spanChild = child.GetValue(SpanBehavior.SpanProperty);
 
-            // get the total height off all non-spanning child objects
-            var totalChildHeight = nonSpanningChildren.Select(x => x.DesiredSize.Height).Sum();
-
-            // remove the total child height from our controls final size and divide it by the total non-spanning child objects
-            // except the last one, since it needs no space after it
-            var spacing = (finalSize.Height - totalChildHeight) / (nonSpanningChildren.Count - 1);
-
-            for (int i = 0; i < children.Count; i++)
+            if (spanChild)
             {
-                var child = children[i];
+                // move any spanning children to the top of the array to push them behind the other controls (visually)
+                children.Move(i, 0);
 
-                var spanChild = child.GetValue(SpanBehavior.SpanProperty);
-
-                if (spanChild)
-                {
-                    // move any spanning children to the top of the array to push them behind the other controls (visually)
-                    children.Move(i, 0);
-
-                    rcChild = rcChild.WithY(0)
-                                     .WithX(0)
-                                     .WithHeight(finalSize.Height)
-                                     .WithWidth(finalSize.Width);
+                rcChild = rcChild.WithY(0)
+                    .WithX(0)
+                    .WithHeight(finalSize.Height)
+                    .WithWidth(finalSize.Width);
 
 
 
-                    child.Arrange(rcChild);
-                    continue;
-                };
-
-                rcChild = rcChild.WithY(rcChild.Y + previousChildSize);
-                previousChildSize = child.DesiredSize.Height;
-                rcChild = rcChild.WithHeight(previousChildSize)
-                                 .WithWidth(Math.Max(finalSize.Width, child.DesiredSize.Width));
-
-                previousChildSize += spacing;
-
                 child.Arrange(rcChild);
-            }
+                continue;
+            };
 
-            return finalSize;
+            rcChild = rcChild.WithY(rcChild.Y + previousChildSize);
+            previousChildSize = child.DesiredSize.Height;
+            rcChild = rcChild.WithHeight(previousChildSize)
+                .WithWidth(Math.Max(finalSize.Width, child.DesiredSize.Width));
+
+            previousChildSize += spacing;
+
+            child.Arrange(rcChild);
         }
+
+        return finalSize;
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/CustomControls/PreCheckItem.axaml.cs b/SPTInstaller/CustomControls/PreCheckItem.axaml.cs
index 28eb41c..5b7182c 100644
--- a/SPTInstaller/CustomControls/PreCheckItem.axaml.cs
+++ b/SPTInstaller/CustomControls/PreCheckItem.axaml.cs
@@ -1,62 +1,57 @@
 using Avalonia;
 using Avalonia.Controls;
-using Avalonia.Controls.Shapes;
-using Avalonia.Threading;
-using ReactiveUI;
-using System.Windows.Input;
 
-namespace SPTInstaller.CustomControls
+namespace SPTInstaller.CustomControls;
+
+public partial class PreCheckItem : UserControl
 {
-    public partial class PreCheckItem : UserControl
+    public PreCheckItem()
     {
-        public PreCheckItem()
-        {
-            InitializeComponent();
-        }
-
-        public string PreCheckName
-        {
-            get => GetValue(PreCheckNameProperty);
-            set => SetValue(PreCheckNameProperty, value);
-        }
-
-        public static readonly StyledProperty<string> PreCheckNameProperty =
-            AvaloniaProperty.Register<PreCheckItem, string>(nameof(PreCheckName));
-
-        public bool IsRunning
-        {
-            get => GetValue(IsRunningProperty);
-            set => SetValue(IsRunningProperty, value);    
-        }
-
-        public static readonly StyledProperty<bool> IsRunningProperty =
-            AvaloniaProperty.Register<PreCheckItem, bool>(nameof(IsRunning));
-
-        public bool IsPending
-        {
-            get => GetValue(IsPendingProperty);
-            set => SetValue(IsPendingProperty, value);
-        }
-
-        public static readonly StyledProperty<bool> IsPendingProperty =
-            AvaloniaProperty.Register<PreCheckItem, bool>(nameof(IsPending));
-
-        public bool Passed
-        {
-            get => GetValue(PassedProperty);
-            set => SetValue(PassedProperty, value);
-        }
-
-        public static readonly StyledProperty<bool> PassedProperty =
-            AvaloniaProperty.Register<PreCheckItem, bool>(nameof(Passed));
-
-        public bool IsRequired
-        {
-            get => GetValue(IsRequiredProperty);
-            set => SetValue(IsRequiredProperty, value);
-        }
-
-        public static readonly StyledProperty<bool> IsRequiredProperty =
-            AvaloniaProperty.Register<PreCheckItem, bool>(nameof(IsRequired));
+        InitializeComponent();
     }
-}
+
+    public string PreCheckName
+    {
+        get => GetValue(PreCheckNameProperty);
+        set => SetValue(PreCheckNameProperty, value);
+    }
+
+    public static readonly StyledProperty<string> PreCheckNameProperty =
+        AvaloniaProperty.Register<PreCheckItem, string>(nameof(PreCheckName));
+
+    public bool IsRunning
+    {
+        get => GetValue(IsRunningProperty);
+        set => SetValue(IsRunningProperty, value);    
+    }
+
+    public static readonly StyledProperty<bool> IsRunningProperty =
+        AvaloniaProperty.Register<PreCheckItem, bool>(nameof(IsRunning));
+
+    public bool IsPending
+    {
+        get => GetValue(IsPendingProperty);
+        set => SetValue(IsPendingProperty, value);
+    }
+
+    public static readonly StyledProperty<bool> IsPendingProperty =
+        AvaloniaProperty.Register<PreCheckItem, bool>(nameof(IsPending));
+
+    public bool Passed
+    {
+        get => GetValue(PassedProperty);
+        set => SetValue(PassedProperty, value);
+    }
+
+    public static readonly StyledProperty<bool> PassedProperty =
+        AvaloniaProperty.Register<PreCheckItem, bool>(nameof(Passed));
+
+    public bool IsRequired
+    {
+        get => GetValue(IsRequiredProperty);
+        set => SetValue(IsRequiredProperty, value);
+    }
+
+    public static readonly StyledProperty<bool> IsRequiredProperty =
+        AvaloniaProperty.Register<PreCheckItem, bool>(nameof(IsRequired));
+}
\ No newline at end of file
diff --git a/SPTInstaller/CustomControls/ProgressableTaskItem.axaml.cs b/SPTInstaller/CustomControls/ProgressableTaskItem.axaml.cs
index 3c7189e..ceaf72c 100644
--- a/SPTInstaller/CustomControls/ProgressableTaskItem.axaml.cs
+++ b/SPTInstaller/CustomControls/ProgressableTaskItem.axaml.cs
@@ -2,76 +2,75 @@ using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Media;
 
-namespace SPTInstaller.CustomControls
+namespace SPTInstaller.CustomControls;
+
+public partial class ProgressableTaskItem : UserControl
 {
-    public partial class ProgressableTaskItem : UserControl
+    public ProgressableTaskItem()
     {
-        public ProgressableTaskItem()
-        {
-            InitializeComponent();
-        }
-
-        public string TaskId
-        {
-            get => GetValue(TaskIdProperty);
-            set => SetValue(TaskIdProperty, value);
-        }
-
-        public static readonly StyledProperty<string> TaskIdProperty =
-            AvaloniaProperty.Register<ProgressableTaskItem, string>(nameof(TaskId));
-
-        public string TaskName
-        {
-            get => GetValue(TaskNameProperty);
-            set => SetValue(TaskNameProperty, value);
-        }
-
-        public static readonly StyledProperty<string> TaskNameProperty =
-            AvaloniaProperty.Register<ProgressableTaskItem, string>(nameof(TaskName));
-
-        public bool IsCompleted
-        {
-            get => GetValue(IsCompletedProperty);
-            set => SetValue(IsCompletedProperty, value);
-        }
-
-        public static readonly StyledProperty<bool> IsCompletedProperty =
-            AvaloniaProperty.Register<ProgressableTaskItem, bool>(nameof(IsCompleted));
-
-        public bool IsRunning
-        {
-            get => GetValue(IsRunningProperty);
-            set => SetValue(IsRunningProperty, value);
-        }
-
-        public static readonly StyledProperty<bool> IsRunningProperty =
-            AvaloniaProperty.Register<ProgressableTaskItem, bool>(nameof(IsRunning));
-
-        public IBrush PendingColor
-        {
-            get => GetValue(PendingColorProperty);
-            set => SetValue(PendingColorProperty, value);
-        }
-
-        public static readonly StyledProperty<IBrush> PendingColorProperty =
-            AvaloniaProperty.Register<ProgressableTaskItem, IBrush>(nameof(PendingColor));
-
-        public IBrush RunningColor
-        {
-            get => GetValue(RunningColorProperty);
-            set => SetValue(RunningColorProperty, value);
-        }
-
-        public static readonly StyledProperty<IBrush> RunningColorProperty =
-            AvaloniaProperty.Register<ProgressableTaskItem, IBrush>(nameof(PendingColor));
-
-        public IBrush CompletedColor
-        {
-            get => GetValue(CompletedColorProperty);
-            set => SetValue(CompletedColorProperty, value);
-        }
-
-        public static readonly StyledProperty<IBrush> CompletedColorProperty =
-            AvaloniaProperty.Register<ProgressableTaskItem, IBrush>(nameof(PendingColor));
+        InitializeComponent();
     }
-}
+
+    public string TaskId
+    {
+        get => GetValue(TaskIdProperty);
+        set => SetValue(TaskIdProperty, value);
+    }
+
+    public static readonly StyledProperty<string> TaskIdProperty =
+        AvaloniaProperty.Register<ProgressableTaskItem, string>(nameof(TaskId));
+
+    public string TaskName
+    {
+        get => GetValue(TaskNameProperty);
+        set => SetValue(TaskNameProperty, value);
+    }
+
+    public static readonly StyledProperty<string> TaskNameProperty =
+        AvaloniaProperty.Register<ProgressableTaskItem, string>(nameof(TaskName));
+
+    public bool IsCompleted
+    {
+        get => GetValue(IsCompletedProperty);
+        set => SetValue(IsCompletedProperty, value);
+    }
+
+    public static readonly StyledProperty<bool> IsCompletedProperty =
+        AvaloniaProperty.Register<ProgressableTaskItem, bool>(nameof(IsCompleted));
+
+    public bool IsRunning
+    {
+        get => GetValue(IsRunningProperty);
+        set => SetValue(IsRunningProperty, value);
+    }
+
+    public static readonly StyledProperty<bool> IsRunningProperty =
+        AvaloniaProperty.Register<ProgressableTaskItem, bool>(nameof(IsRunning));
+
+    public IBrush PendingColor
+    {
+        get => GetValue(PendingColorProperty);
+        set => SetValue(PendingColorProperty, value);
+    }
+
+    public static readonly StyledProperty<IBrush> PendingColorProperty =
+        AvaloniaProperty.Register<ProgressableTaskItem, IBrush>(nameof(PendingColor));
+
+    public IBrush RunningColor
+    {
+        get => GetValue(RunningColorProperty);
+        set => SetValue(RunningColorProperty, value);
+    }
+
+    public static readonly StyledProperty<IBrush> RunningColorProperty =
+        AvaloniaProperty.Register<ProgressableTaskItem, IBrush>(nameof(PendingColor));
+
+    public IBrush CompletedColor
+    {
+        get => GetValue(CompletedColorProperty);
+        set => SetValue(CompletedColorProperty, value);
+    }
+
+    public static readonly StyledProperty<IBrush> CompletedColorProperty =
+        AvaloniaProperty.Register<ProgressableTaskItem, IBrush>(nameof(PendingColor));
+}
\ No newline at end of file
diff --git a/SPTInstaller/CustomControls/ProgressableTaskList.axaml.cs b/SPTInstaller/CustomControls/ProgressableTaskList.axaml.cs
index fbcd063..d725dac 100644
--- a/SPTInstaller/CustomControls/ProgressableTaskList.axaml.cs
+++ b/SPTInstaller/CustomControls/ProgressableTaskList.axaml.cs
@@ -2,96 +2,93 @@ using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Media;
 using Avalonia.Threading;
-using DynamicData;
 using DynamicData.Binding;
 using SPTInstaller.Models;
-using System;
 using System.Collections.ObjectModel;
 using System.Linq;
 using System.Threading.Tasks;
 
-namespace SPTInstaller.CustomControls
+namespace SPTInstaller.CustomControls;
+
+public partial class ProgressableTaskList : UserControl
 {
-    public partial class ProgressableTaskList : UserControl
+    public ProgressableTaskList()
     {
-        public ProgressableTaskList()
+        InitializeComponent();
+
+        this.AttachedToVisualTree += ProgressableTaskList_AttachedToVisualTree;
+    }
+
+    private int _taskProgress;
+    public int TaskProgress
+    {
+        get => _taskProgress;
+        set => SetAndRaise(ProgressableTaskList.TaskProgressProperty, ref _taskProgress, value);
+    }
+
+    public static readonly DirectProperty<ProgressableTaskList, int> TaskProgressProperty =
+        AvaloniaProperty.RegisterDirect<ProgressableTaskList, int>(nameof(TaskProgress), o => o.TaskProgress);
+
+    public ObservableCollection<InstallerTaskBase> Tasks
+    {
+        get => GetValue(TasksProperty);
+        set => SetValue(TasksProperty, value);
+    }
+
+    public static readonly StyledProperty<ObservableCollection<InstallerTaskBase>> TasksProperty =
+        AvaloniaProperty.Register<ProgressableTaskList, ObservableCollection<InstallerTaskBase>>(nameof(Tasks));
+
+    public IBrush PendingColor
+    {
+        get => GetValue(PendingColorProperty);
+        set => SetValue(PendingColorProperty, value);
+    }
+
+    public static readonly StyledProperty<IBrush> PendingColorProperty =
+        AvaloniaProperty.Register<ProgressableTaskList, IBrush>(nameof(PendingColor));
+
+    public IBrush RunningColor
+    {
+        get => GetValue(RunningColorProperty);
+        set => SetValue(RunningColorProperty, value);
+    }
+
+    public static readonly StyledProperty<IBrush> RunningColorProperty =
+        AvaloniaProperty.Register<ProgressableTaskList, IBrush>(nameof(PendingColor));
+
+    public IBrush CompletedColor
+    {
+        get => GetValue(CompletedColorProperty);
+        set => SetValue(CompletedColorProperty, value);
+    }
+
+    public static readonly StyledProperty<IBrush> CompletedColorProperty =
+        AvaloniaProperty.Register<ProgressableTaskList, IBrush>(nameof(PendingColor));
+
+    private void UpdateTaskProgress()
+    {
+        Dispatcher.UIThread.InvokeAsync(async () =>
         {
-            InitializeComponent();
+            var completedTasks = Tasks.Where(x => x.IsCompleted == true).Count();
 
-            this.AttachedToVisualTree += ProgressableTaskList_AttachedToVisualTree;
-        }
+            var progress = (int)Math.Floor((double)completedTasks / (Tasks.Count - 1) * 100);
 
-        private int _taskProgress;
-        public int TaskProgress
-        {
-            get => _taskProgress;
-            set => SetAndRaise(ProgressableTaskList.TaskProgressProperty, ref _taskProgress, value);
-        }
-
-        public static readonly DirectProperty<ProgressableTaskList, int> TaskProgressProperty =
-            AvaloniaProperty.RegisterDirect<ProgressableTaskList, int>(nameof(TaskProgress), o => o.TaskProgress);
-
-        public ObservableCollection<InstallerTaskBase> Tasks
-        {
-            get => GetValue(TasksProperty);
-            set => SetValue(TasksProperty, value);
-        }
-
-        public static readonly StyledProperty<ObservableCollection<InstallerTaskBase>> TasksProperty =
-            AvaloniaProperty.Register<ProgressableTaskList, ObservableCollection<InstallerTaskBase>>(nameof(Tasks));
-
-        public IBrush PendingColor
-        {
-            get => GetValue(PendingColorProperty);
-            set => SetValue(PendingColorProperty, value);
-        }
-
-        public static readonly StyledProperty<IBrush> PendingColorProperty =
-            AvaloniaProperty.Register<ProgressableTaskList, IBrush>(nameof(PendingColor));
-
-        public IBrush RunningColor
-        {
-            get => GetValue(RunningColorProperty);
-            set => SetValue(RunningColorProperty, value);
-        }
-
-        public static readonly StyledProperty<IBrush> RunningColorProperty =
-            AvaloniaProperty.Register<ProgressableTaskList, IBrush>(nameof(PendingColor));
-
-        public IBrush CompletedColor
-        {
-            get => GetValue(CompletedColorProperty);
-            set => SetValue(CompletedColorProperty, value);
-        }
-
-        public static readonly StyledProperty<IBrush> CompletedColorProperty =
-            AvaloniaProperty.Register<ProgressableTaskList, IBrush>(nameof(PendingColor));
-
-        private void UpdateTaskProgress()
-        {
-            Dispatcher.UIThread.InvokeAsync(async () =>
+            for(; TaskProgress < progress;)
             {
-                var completedTasks = Tasks.Where(x => x.IsCompleted == true).Count();
-
-                var progress = (int)Math.Floor((double)completedTasks / (Tasks.Count - 1) * 100);
-
-                for(; TaskProgress < progress;)
-                {
-                    TaskProgress += 1;
-                    await Task.Delay(1);
-                }
-            });
-        }
-
-        private void ProgressableTaskList_AttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
-        {
-            if (Tasks == null) return;
-
-            foreach (var task in Tasks)
-            {
-                task.WhenPropertyChanged(x => x.IsCompleted)
-                    .Subscribe(x => UpdateTaskProgress());
+                TaskProgress += 1;
+                await Task.Delay(1);
             }
+        });
+    }
+
+    private void ProgressableTaskList_AttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
+    {
+        if (Tasks == null) return;
+
+        foreach (var task in Tasks)
+        {
+            task.WhenPropertyChanged(x => x.IsCompleted)
+                .Subscribe(x => UpdateTaskProgress());
         }
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/CustomControls/TaskDetails.axaml.cs b/SPTInstaller/CustomControls/TaskDetails.axaml.cs
index f1be930..31132c4 100644
--- a/SPTInstaller/CustomControls/TaskDetails.axaml.cs
+++ b/SPTInstaller/CustomControls/TaskDetails.axaml.cs
@@ -1,58 +1,57 @@
 using Avalonia;
 using Avalonia.Controls;
 
-namespace SPTInstaller.CustomControls
+namespace SPTInstaller.CustomControls;
+
+public partial class TaskDetails : UserControl
 {
-    public partial class TaskDetails : UserControl
+    public TaskDetails()
     {
-        public TaskDetails()
-        {
-            InitializeComponent();
-        }
-
-        public string Message
-        {
-            get => GetValue(MessageProperty);
-            set => SetValue(MessageProperty, value);
-        }
-
-        public static readonly StyledProperty<string> MessageProperty =
-            AvaloniaProperty.Register<TaskDetails, string>(nameof(Message));
-
-        public string Details
-        {
-            get => GetValue(DetailsProperty);
-            set => SetValue(DetailsProperty, value);
-        }
-
-        public static readonly StyledProperty<string> DetailsProperty =
-            AvaloniaProperty.Register<TaskDetails, string>(nameof(Details));
-
-        public int Progress
-        {
-            get => GetValue(ProgressProperty);
-            set => SetValue(ProgressProperty, value);
-        }
-
-        public static readonly StyledProperty<int> ProgressProperty =
-            AvaloniaProperty.Register<TaskDetails, int>(nameof(Progress));
-
-        public bool ShowProgress
-        {
-            get => GetValue(ShowProgressProperty);
-            set => SetValue(ShowProgressProperty, value);
-        }
-
-        public static readonly StyledProperty<bool> ShowProgressProperty =
-            AvaloniaProperty.Register<TaskDetails, bool>(nameof(ShowProgress));
-
-        public bool IndeterminateProgress
-        {
-            get => GetValue(IndeterminateProgressProperty);
-            set => SetValue(IndeterminateProgressProperty, value);
-        }
-
-        public static readonly StyledProperty<bool> IndeterminateProgressProperty =
-            AvaloniaProperty.Register<TaskDetails, bool>(nameof(IndeterminateProgress));
+        InitializeComponent();
     }
-}
+
+    public string Message
+    {
+        get => GetValue(MessageProperty);
+        set => SetValue(MessageProperty, value);
+    }
+
+    public static readonly StyledProperty<string> MessageProperty =
+        AvaloniaProperty.Register<TaskDetails, string>(nameof(Message));
+
+    public string Details
+    {
+        get => GetValue(DetailsProperty);
+        set => SetValue(DetailsProperty, value);
+    }
+
+    public static readonly StyledProperty<string> DetailsProperty =
+        AvaloniaProperty.Register<TaskDetails, string>(nameof(Details));
+
+    public int Progress
+    {
+        get => GetValue(ProgressProperty);
+        set => SetValue(ProgressProperty, value);
+    }
+
+    public static readonly StyledProperty<int> ProgressProperty =
+        AvaloniaProperty.Register<TaskDetails, int>(nameof(Progress));
+
+    public bool ShowProgress
+    {
+        get => GetValue(ShowProgressProperty);
+        set => SetValue(ShowProgressProperty, value);
+    }
+
+    public static readonly StyledProperty<bool> ShowProgressProperty =
+        AvaloniaProperty.Register<TaskDetails, bool>(nameof(ShowProgress));
+
+    public bool IndeterminateProgress
+    {
+        get => GetValue(IndeterminateProgressProperty);
+        set => SetValue(IndeterminateProgressProperty, value);
+    }
+
+    public static readonly StyledProperty<bool> IndeterminateProgressProperty =
+        AvaloniaProperty.Register<TaskDetails, bool>(nameof(IndeterminateProgress));
+}
\ No newline at end of file
diff --git a/SPTInstaller/CustomControls/TitleBar.axaml.cs b/SPTInstaller/CustomControls/TitleBar.axaml.cs
index 5c0c336..fc17d58 100644
--- a/SPTInstaller/CustomControls/TitleBar.axaml.cs
+++ b/SPTInstaller/CustomControls/TitleBar.axaml.cs
@@ -4,74 +4,73 @@ using Avalonia.Markup.Xaml;
 using Avalonia.Media;
 using System.Windows.Input;
 
-namespace SPTInstaller.CustomControls
+namespace SPTInstaller.CustomControls;
+
+public partial class TitleBar : UserControl
 {
-    public partial class TitleBar : UserControl
+    public TitleBar()
     {
-        public TitleBar()
-        {
-            InitializeComponent();
-        }
-
-        private void InitializeComponent()
-        {
-            AvaloniaXamlLoader.Load(this);
-        }
-
-        public static readonly StyledProperty<string> TitleProperty =
-            AvaloniaProperty.Register<TitleBar, string>(nameof(Title));
-
-        public string Title
-        {
-            get => GetValue(TitleProperty);
-            set => SetValue(TitleProperty, value);
-        }
-
-        public static readonly StyledProperty<IBrush> ButtonForegroundProperty =
-            AvaloniaProperty.Register<TitleBar, IBrush>(nameof(ButtonForeground));
-
-        public IBrush ButtonForeground
-        {
-            get => GetValue(ButtonForegroundProperty);
-            set => SetValue(ButtonForegroundProperty, value);
-        }
-
-        public static new readonly StyledProperty<IBrush> ForegroundProperty =
-            AvaloniaProperty.Register<TitleBar, IBrush>(nameof(Foreground));
-
-        public new IBrush Foreground
-        {
-            get => GetValue(ForegroundProperty);
-            set => SetValue(ForegroundProperty, value);
-        }
-
-        public static new readonly StyledProperty<IBrush> BackgroundProperty =
-            AvaloniaProperty.Register<TitleBar, IBrush>(nameof(Background));
-
-        public new IBrush Background
-        {
-            get => GetValue(BackgroundProperty);
-            set => SetValue(BackgroundProperty, value);
-        }
-
-        //Close Button Command (X Button) Property
-        public static readonly StyledProperty<ICommand> XButtonCommandProperty =
-            AvaloniaProperty.Register<TitleBar, ICommand>(nameof(XButtonCommand));
-
-        public ICommand XButtonCommand
-        {
-            get => GetValue(XButtonCommandProperty);
-            set => SetValue(XButtonCommandProperty, value);
-        }
-
-        //Minimize Button Command (- Button) Property
-        public static readonly StyledProperty<ICommand> MinButtonCommandProperty =
-            AvaloniaProperty.Register<TitleBar, ICommand>(nameof(MinButtonCommand));
-
-        public ICommand MinButtonCommand
-        {
-            get => GetValue(MinButtonCommandProperty);
-            set => SetValue(MinButtonCommandProperty, value);
-        }
+        InitializeComponent();
     }
-}
+
+    private void InitializeComponent()
+    {
+        AvaloniaXamlLoader.Load(this);
+    }
+
+    public static readonly StyledProperty<string> TitleProperty =
+        AvaloniaProperty.Register<TitleBar, string>(nameof(Title));
+
+    public string Title
+    {
+        get => GetValue(TitleProperty);
+        set => SetValue(TitleProperty, value);
+    }
+
+    public static readonly StyledProperty<IBrush> ButtonForegroundProperty =
+        AvaloniaProperty.Register<TitleBar, IBrush>(nameof(ButtonForeground));
+
+    public IBrush ButtonForeground
+    {
+        get => GetValue(ButtonForegroundProperty);
+        set => SetValue(ButtonForegroundProperty, value);
+    }
+
+    public static new readonly StyledProperty<IBrush> ForegroundProperty =
+        AvaloniaProperty.Register<TitleBar, IBrush>(nameof(Foreground));
+
+    public new IBrush Foreground
+    {
+        get => GetValue(ForegroundProperty);
+        set => SetValue(ForegroundProperty, value);
+    }
+
+    public static new readonly StyledProperty<IBrush> BackgroundProperty =
+        AvaloniaProperty.Register<TitleBar, IBrush>(nameof(Background));
+
+    public new IBrush Background
+    {
+        get => GetValue(BackgroundProperty);
+        set => SetValue(BackgroundProperty, value);
+    }
+
+    //Close Button Command (X Button) Property
+    public static readonly StyledProperty<ICommand> XButtonCommandProperty =
+        AvaloniaProperty.Register<TitleBar, ICommand>(nameof(XButtonCommand));
+
+    public ICommand XButtonCommand
+    {
+        get => GetValue(XButtonCommandProperty);
+        set => SetValue(XButtonCommandProperty, value);
+    }
+
+    //Minimize Button Command (- Button) Property
+    public static readonly StyledProperty<ICommand> MinButtonCommandProperty =
+        AvaloniaProperty.Register<TitleBar, ICommand>(nameof(MinButtonCommand));
+
+    public ICommand MinButtonCommand
+    {
+        get => GetValue(MinButtonCommandProperty);
+        set => SetValue(MinButtonCommandProperty, value);
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Helpers/DownloadCacheHelper.cs b/SPTInstaller/Helpers/DownloadCacheHelper.cs
index 4831e98..30cb479 100644
--- a/SPTInstaller/Helpers/DownloadCacheHelper.cs
+++ b/SPTInstaller/Helpers/DownloadCacheHelper.cs
@@ -1,146 +1,142 @@
-using HttpClientProgress;
+using System.Net.Http;
+using System.Threading.Tasks;
 using Serilog;
 using SPTInstaller.Models;
-using System;
-using System.IO;
-using System.Net.Http;
-using System.Threading.Tasks;
 
-namespace SPTInstaller.Aki.Helper
+namespace SPTInstaller.Helpers;
+
+public static class DownloadCacheHelper
 {
-    public static class DownloadCacheHelper
+    private static HttpClient _httpClient = new() { Timeout = TimeSpan.FromHours(1) };
+
+    private static string _cachePath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "spt-installer/cache");
+
+    private static bool CheckCache(FileInfo cacheFile, string expectedHash = null)
     {
-        private static HttpClient _httpClient = new HttpClient() { Timeout = TimeSpan.FromHours(1) };
-
-        private static string _cachePath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "spt-installer/cache");
-
-        private static bool CheckCache(FileInfo cacheFile, string expectedHash = null)
+        try
         {
-            try
+            cacheFile.Refresh();
+            Directory.CreateDirectory(_cachePath);
+
+            if (cacheFile.Exists)
             {
+                if (expectedHash != null && FileHashHelper.CheckHash(cacheFile, expectedHash))
+                {
+                    Log.Information($"Using cached file: {cacheFile.Name} - Hash: {expectedHash}");
+                    return true;
+                }
+
+                cacheFile.Delete();
                 cacheFile.Refresh();
-                Directory.CreateDirectory(_cachePath);
-
-                if (cacheFile.Exists)
-                {
-                    if (expectedHash != null && FileHashHelper.CheckHash(cacheFile, expectedHash))
-                    {
-                        Log.Information($"Using cached file: {cacheFile.Name} - Hash: {expectedHash}");
-                        return true;
-                    }
-
-                    cacheFile.Delete();
-                    cacheFile.Refresh();
-                }
-
-                return false;
-            }
-            catch
-            {
-                return false;
             }
+
+            return false;
         }
-
-        private static async Task<Result> DownloadFile(FileInfo outputFile, string targetLink, IProgress<double> progress, string expectedHash = null)
+        catch
         {
-            try
-            {
-                // Use the provided extension method
-                using (var file = new FileStream(outputFile.FullName, FileMode.Create, FileAccess.Write, FileShare.None))
-                    await _httpClient.DownloadDataAsync(targetLink, file, progress);
-
-                outputFile.Refresh();
-
-                if (!outputFile.Exists)
-                {
-                    return Result.FromError($"Failed to download {outputFile.Name}");
-                }
-
-                if (expectedHash != null && !FileHashHelper.CheckHash(outputFile, expectedHash))
-                {
-                    return Result.FromError("Hash mismatch");
-                }
-
-                return Result.FromSuccess();
-            }
-            catch (Exception ex)
-            {
-                return Result.FromError(ex.Message);
-            }
-        }
-
-        private static async Task<Result> ProcessInboundStreamAsync(FileInfo cacheFile, Stream downloadStream, string expectedHash = null)
-        {
-            try
-            {
-                if (CheckCache(cacheFile, expectedHash)) return Result.FromSuccess();
-
-                using var patcherFileStream = cacheFile.Open(FileMode.Create);
-                {
-                    await downloadStream.CopyToAsync(patcherFileStream);
-                }
-
-                patcherFileStream.Close();
-
-                if (expectedHash != null && !FileHashHelper.CheckHash(cacheFile, expectedHash))
-                {
-                    return Result.FromError("Hash mismatch");
-                }
-
-                return Result.FromSuccess();
-            }
-            catch(Exception ex)
-            {
-                return Result.FromError(ex.Message);
-            }
-        }
-
-        private static async Task<Result> ProcessInboundFileAsync(FileInfo cacheFile, string targetLink, IProgress<double> progress, string expectedHash = null)
-        {
-            try
-            {
-                if (CheckCache(cacheFile, expectedHash)) return Result.FromSuccess();
-
-                return await DownloadFile(cacheFile, targetLink, progress, expectedHash);
-            }
-            catch(Exception ex)
-            {
-                return Result.FromError(ex.Message);
-            }
-        }
-
-        public static async Task<FileInfo?> GetOrDownloadFileAsync(string fileName, string targetLink, IProgress<double> progress, string expectedHash = null)
-        {
-            FileInfo cacheFile = new FileInfo(Path.Join(_cachePath, fileName));
-
-            try
-            {
-                var result = await ProcessInboundFileAsync(cacheFile, targetLink, progress, expectedHash);
-
-                return result.Succeeded ? cacheFile : null;
-            }
-            catch(Exception ex)
-            {
-                Log.Error(ex, $"Error while getting file: {fileName}");
-                return null;
-            }
-        }
-
-        public static async Task<FileInfo?> GetOrDownloadFileAsync(string fileName, Stream fileDownloadStream, string expectedHash = null)
-        {
-            FileInfo cacheFile = new FileInfo(Path.Join(_cachePath, fileName));
-
-            try
-            {
-                var result = await ProcessInboundStreamAsync(cacheFile, fileDownloadStream, expectedHash);
-
-                return result.Succeeded ? cacheFile : null;
-            }
-            catch(Exception ex)
-            {
-                Log.Error(ex, $"Error while getting file: {fileName}");
-                return null;
-            }
+            return false;
         }
     }
-}
+
+    private static async Task<Result> DownloadFile(FileInfo outputFile, string targetLink, IProgress<double> progress, string expectedHash = null)
+    {
+        try
+        {
+            // Use the provided extension method
+            using (var file = new FileStream(outputFile.FullName, FileMode.Create, FileAccess.Write, FileShare.None))
+                await _httpClient.DownloadDataAsync(targetLink, file, progress);
+
+            outputFile.Refresh();
+
+            if (!outputFile.Exists)
+            {
+                return Result.FromError($"Failed to download {outputFile.Name}");
+            }
+
+            if (expectedHash != null && !FileHashHelper.CheckHash(outputFile, expectedHash))
+            {
+                return Result.FromError("Hash mismatch");
+            }
+
+            return Result.FromSuccess();
+        }
+        catch (Exception ex)
+        {
+            return Result.FromError(ex.Message);
+        }
+    }
+
+    private static async Task<Result> ProcessInboundStreamAsync(FileInfo cacheFile, Stream downloadStream, string expectedHash = null)
+    {
+        try
+        {
+            if (CheckCache(cacheFile, expectedHash)) return Result.FromSuccess();
+
+            using var patcherFileStream = cacheFile.Open(FileMode.Create);
+            {
+                await downloadStream.CopyToAsync(patcherFileStream);
+            }
+
+            patcherFileStream.Close();
+
+            if (expectedHash != null && !FileHashHelper.CheckHash(cacheFile, expectedHash))
+            {
+                return Result.FromError("Hash mismatch");
+            }
+
+            return Result.FromSuccess();
+        }
+        catch(Exception ex)
+        {
+            return Result.FromError(ex.Message);
+        }
+    }
+
+    private static async Task<Result> ProcessInboundFileAsync(FileInfo cacheFile, string targetLink, IProgress<double> progress, string expectedHash = null)
+    {
+        try
+        {
+            if (CheckCache(cacheFile, expectedHash)) return Result.FromSuccess();
+
+            return await DownloadFile(cacheFile, targetLink, progress, expectedHash);
+        }
+        catch(Exception ex)
+        {
+            return Result.FromError(ex.Message);
+        }
+    }
+
+    public static async Task<FileInfo?> GetOrDownloadFileAsync(string fileName, string targetLink, IProgress<double> progress, string expectedHash = null)
+    {
+        var cacheFile = new FileInfo(Path.Join(_cachePath, fileName));
+
+        try
+        {
+            var result = await ProcessInboundFileAsync(cacheFile, targetLink, progress, expectedHash);
+
+            return result.Succeeded ? cacheFile : null;
+        }
+        catch(Exception ex)
+        {
+            Log.Error(ex, $"Error while getting file: {fileName}");
+            return null;
+        }
+    }
+
+    public static async Task<FileInfo?> GetOrDownloadFileAsync(string fileName, Stream fileDownloadStream, string expectedHash = null)
+    {
+        var cacheFile = new FileInfo(Path.Join(_cachePath, fileName));
+
+        try
+        {
+            var result = await ProcessInboundStreamAsync(cacheFile, fileDownloadStream, expectedHash);
+
+            return result.Succeeded ? cacheFile : null;
+        }
+        catch(Exception ex)
+        {
+            Log.Error(ex, $"Error while getting file: {fileName}");
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Helpers/FileHashHelper.cs b/SPTInstaller/Helpers/FileHashHelper.cs
index 2b70e55..315fbe3 100644
--- a/SPTInstaller/Helpers/FileHashHelper.cs
+++ b/SPTInstaller/Helpers/FileHashHelper.cs
@@ -1,38 +1,34 @@
-using Gitea.Model;
-using System;
-using System.IO;
-using System.Linq;
+using System.Linq;
 using System.Security.Cryptography;
 using System.Text.RegularExpressions;
+using Gitea.Model;
 
-namespace SPTInstaller.Aki.Helper
+namespace SPTInstaller.Helpers;
+
+public static class FileHashHelper
 {
-    public static class FileHashHelper
+    public static string? GetGiteaReleaseHash(Release release)
     {
-        public static string GetGiteaReleaseHash(Release release)
+        var regex = Regex.Match(release.Body, @"Release Hash: (?<hash>\S+)");
+
+        if (regex.Success)
         {
-            var regex = Regex.Match(release.Body, @"Release Hash: (?<hash>\S+)");
-
-            if (regex.Success)
-            {
-                return regex.Groups["hash"].Value;
-            }
-
-            return null;
+            return regex.Groups["hash"].Value;
         }
 
-        public static bool CheckHash(FileInfo file, string expectedHash)
-        {
-            using (MD5 md5Service = MD5.Create())
-            using (var sourceStream = file.OpenRead())
-            {
-                byte[] sourceHash = md5Service.ComputeHash(sourceStream);
-                byte[] expectedHashBytes = Convert.FromBase64String(expectedHash);
-
-                bool matched = Enumerable.SequenceEqual(sourceHash, expectedHashBytes);
-
-                return matched;
-            }
-        }
+        return null;
     }
-}
+
+    public static bool CheckHash(FileInfo file, string expectedHash)
+    {
+        using var md5Service = MD5.Create();
+        using var sourceStream = file.OpenRead();
+        
+        var sourceHash = md5Service.ComputeHash(sourceStream);
+        var expectedHashBytes = Convert.FromBase64String(expectedHash);
+
+        var matched = Enumerable.SequenceEqual(sourceHash, expectedHashBytes);
+
+        return matched;
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Helpers/FileHelper.cs b/SPTInstaller/Helpers/FileHelper.cs
index d624668..56de581 100644
--- a/SPTInstaller/Helpers/FileHelper.cs
+++ b/SPTInstaller/Helpers/FileHelper.cs
@@ -1,90 +1,86 @@
-using ReactiveUI;
+using System.Text.RegularExpressions;
 using Serilog;
 using SPTInstaller.Models;
-using System;
-using System.IO;
-using System.Text.RegularExpressions;
 
-namespace SPTInstaller.Aki.Helper
+namespace SPTInstaller.Helpers;
+
+public static class FileHelper
 {
-    public static class FileHelper
+    private static Result IterateDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
     {
-        private static Result IterateDirectories(DirectoryInfo sourceDir, DirectoryInfo targetDir)
+        try
         {
-            try
+            foreach (var dir in sourceDir.GetDirectories("*", SearchOption.AllDirectories))
             {
-                foreach (var dir in sourceDir.GetDirectories("*", SearchOption.AllDirectories))
-                {
-                    Directory.CreateDirectory(dir.FullName.Replace(sourceDir.FullName, targetDir.FullName));
-                }
-                return Result.FromSuccess();
-            }
-            catch (Exception ex) 
-            {
-                Log.Error(ex, "Error while creating directories");
-                return Result.FromError(ex.Message);
+                Directory.CreateDirectory(dir.FullName.Replace(sourceDir.FullName, targetDir.FullName));
             }
+            return Result.FromSuccess();
         }
-
-        private static Result IterateFiles(DirectoryInfo sourceDir, DirectoryInfo targetDir, Action<string, int> updateCallback = null)
+        catch (Exception ex) 
         {
-            try
-            {
-                int totalFiles = sourceDir.GetFiles("*.*", SearchOption.AllDirectories).Length;
-                int processedFiles = 0;
-
-                foreach (var file in sourceDir.GetFiles("*.*", SearchOption.AllDirectories))
-                {
-                    updateCallback?.Invoke(file.Name, (int)Math.Floor(((double)processedFiles / totalFiles) * 100));
-
-                    File.Copy(file.FullName, file.FullName.Replace(sourceDir.FullName, targetDir.FullName), true);
-                    processedFiles++;
-                }
-
-                return Result.FromSuccess();
-            }
-            catch (Exception ex)
-            {
-                Log.Error(ex, "Error while copying files");
-                return Result.FromError(ex.Message);
-            }
-        }
-
-        public static string GetRedactedPath(string path)
-        {
-            var nameMatched = Regex.Match(path, @".:\\[uU]sers\\(?<NAME>[^\\]+)");
-
-            if (nameMatched.Success)
-            {
-                var name = nameMatched.Groups["NAME"].Value;
-                return path.Replace(name, "-REDACTED-");
-            }
-
-            return path;
-        }
-
-        public static Result CopyDirectoryWithProgress(DirectoryInfo sourceDir, DirectoryInfo targetDir, IProgress<double> progress = null) =>
-            CopyDirectoryWithProgress(sourceDir, targetDir, (msg, prog) => progress?.Report(prog));
-
-        public static Result CopyDirectoryWithProgress(DirectoryInfo sourceDir, DirectoryInfo targetDir, Action<string, int> updateCallback = null)
-        {
-            try
-            {
-                var iterateDirectoriesResult = IterateDirectories(sourceDir, targetDir);
-
-                if(!iterateDirectoriesResult.Succeeded) return iterateDirectoriesResult;
-
-                var iterateFilesResult = IterateFiles(sourceDir, targetDir, updateCallback);
-
-                if (!iterateFilesResult.Succeeded) return iterateDirectoriesResult;
-
-                return Result.FromSuccess();
-            }
-            catch (Exception ex)
-            {
-                Log.Error(ex, "Error during directory copy");
-                return Result.FromError(ex.Message);
-            }
+            Log.Error(ex, "Error while creating directories");
+            return Result.FromError(ex.Message);
         }
     }
-}
+
+    private static Result IterateFiles(DirectoryInfo sourceDir, DirectoryInfo targetDir, Action<string, int> updateCallback = null)
+    {
+        try
+        {
+            int totalFiles = sourceDir.GetFiles("*.*", SearchOption.AllDirectories).Length;
+            int processedFiles = 0;
+
+            foreach (var file in sourceDir.GetFiles("*.*", SearchOption.AllDirectories))
+            {
+                updateCallback?.Invoke(file.Name, (int)Math.Floor(((double)processedFiles / totalFiles) * 100));
+
+                File.Copy(file.FullName, file.FullName.Replace(sourceDir.FullName, targetDir.FullName), true);
+                processedFiles++;
+            }
+
+            return Result.FromSuccess();
+        }
+        catch (Exception ex)
+        {
+            Log.Error(ex, "Error while copying files");
+            return Result.FromError(ex.Message);
+        }
+    }
+
+    public static string GetRedactedPath(string path)
+    {
+        var nameMatched = Regex.Match(path, @".:\\[uU]sers\\(?<NAME>[^\\]+)");
+
+        if (nameMatched.Success)
+        {
+            var name = nameMatched.Groups["NAME"].Value;
+            return path.Replace(name, "-REDACTED-");
+        }
+
+        return path;
+    }
+
+    public static Result CopyDirectoryWithProgress(DirectoryInfo sourceDir, DirectoryInfo targetDir, IProgress<double> progress = null) =>
+        CopyDirectoryWithProgress(sourceDir, targetDir, (msg, prog) => progress?.Report(prog));
+
+    public static Result CopyDirectoryWithProgress(DirectoryInfo sourceDir, DirectoryInfo targetDir, Action<string, int> updateCallback = null)
+    {
+        try
+        {
+            var iterateDirectoriesResult = IterateDirectories(sourceDir, targetDir);
+
+            if(!iterateDirectoriesResult.Succeeded) return iterateDirectoriesResult;
+
+            var iterateFilesResult = IterateFiles(sourceDir, targetDir, updateCallback);
+
+            if (!iterateFilesResult.Succeeded) return iterateDirectoriesResult;
+
+            return Result.FromSuccess();
+        }
+        catch (Exception ex)
+        {
+            Log.Error(ex, "Error during directory copy");
+            return Result.FromError(ex.Message);
+        }
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Helpers/HttpClientProgressExtensions.cs b/SPTInstaller/Helpers/HttpClientProgressExtensions.cs
index 3568717..d77154d 100644
--- a/SPTInstaller/Helpers/HttpClientProgressExtensions.cs
+++ b/SPTInstaller/Helpers/HttpClientProgressExtensions.cs
@@ -1,57 +1,54 @@
-using System;
-using System.IO;
-using System.Net.Http;
+using System.Net.Http;
 using System.Threading;
 using System.Threading.Tasks;
 
-namespace HttpClientProgress
-{
-    public static class HttpClientProgressExtensions
-    {
-        public static async Task DownloadDataAsync(this HttpClient client, string requestUrl, Stream destination, IProgress<double> progress = null, CancellationToken cancellationToken = default(CancellationToken))
-        {
-            using (var response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead))
-            {
-                var contentLength = response.Content.Headers.ContentLength;
-                using (var download = await response.Content.ReadAsStreamAsync())
-                {
-                    // no progress... no contentLength... very sad
-                    if (progress is null || !contentLength.HasValue)
-                    {
-                        await download.CopyToAsync(destination);
-                        return;
-                    }
-                    // Such progress and contentLength much reporting Wow!
-                    var progressWrapper = new Progress<long>(totalBytes => progress.Report(GetProgressPercentage(totalBytes, contentLength.Value)));
-                    await download.CopyToAsync(destination, 81920, progressWrapper, cancellationToken);
-                }
-            }
+namespace SPTInstaller.Helpers;
 
-            float GetProgressPercentage(float totalBytes, float currentBytes) => (totalBytes / currentBytes) * 100f;
+public static class HttpClientProgressExtensions
+{
+    public static async Task DownloadDataAsync(this HttpClient client, string requestUrl, Stream destination, IProgress<double> progress = null, CancellationToken cancellationToken = default(CancellationToken))
+    {
+        using (var response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead))
+        {
+            var contentLength = response.Content.Headers.ContentLength;
+            using (var download = await response.Content.ReadAsStreamAsync())
+            {
+                // no progress... no contentLength... very sad
+                if (progress is null || !contentLength.HasValue)
+                {
+                    await download.CopyToAsync(destination);
+                    return;
+                }
+                // Such progress and contentLength much reporting Wow!
+                var progressWrapper = new Progress<long>(totalBytes => progress.Report(GetProgressPercentage(totalBytes, contentLength.Value)));
+                await download.CopyToAsync(destination, 81920, progressWrapper, cancellationToken);
+            }
         }
 
-        static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default(CancellationToken))
-        {
-            if (bufferSize < 0)
-                throw new ArgumentOutOfRangeException(nameof(bufferSize));
-            if (source is null)
-                throw new ArgumentNullException(nameof(source));
-            if (!source.CanRead)
-                throw new InvalidOperationException($"'{nameof(source)}' is not readable.");
-            if (destination == null)
-                throw new ArgumentNullException(nameof(destination));
-            if (!destination.CanWrite)
-                throw new InvalidOperationException($"'{nameof(destination)}' is not writable.");
+        float GetProgressPercentage(float totalBytes, float currentBytes) => (totalBytes / currentBytes) * 100f;
+    }
 
-            var buffer = new byte[bufferSize];
-            long totalBytesRead = 0;
-            int bytesRead;
-            while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
-            {
-                await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
-                totalBytesRead += bytesRead;
-                progress?.Report(totalBytesRead);
-            }
+    static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<long> progress = null, CancellationToken cancellationToken = default(CancellationToken))
+    {
+        if (bufferSize < 0)
+            throw new ArgumentOutOfRangeException(nameof(bufferSize));
+        if (source is null)
+            throw new ArgumentNullException(nameof(source));
+        if (!source.CanRead)
+            throw new InvalidOperationException($"'{nameof(source)}' is not readable.");
+        if (destination == null)
+            throw new ArgumentNullException(nameof(destination));
+        if (!destination.CanWrite)
+            throw new InvalidOperationException($"'{nameof(destination)}' is not writable.");
+
+        var buffer = new byte[bufferSize];
+        long totalBytesRead = 0;
+        int bytesRead;
+        while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
+        {
+            await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
+            totalBytesRead += bytesRead;
+            progress?.Report(totalBytesRead);
         }
     }
 }
\ No newline at end of file
diff --git a/SPTInstaller/Helpers/PreCheckHelper.cs b/SPTInstaller/Helpers/PreCheckHelper.cs
index 4380020..f9f9d3b 100644
--- a/SPTInstaller/Helpers/PreCheckHelper.cs
+++ b/SPTInstaller/Helpers/PreCheckHelper.cs
@@ -1,40 +1,37 @@
-using Microsoft.Win32;
-using SPTInstaller.Models;
-using System;
-using System.Diagnostics;
-using System.IO;
+using System.Diagnostics;
 using System.Runtime.InteropServices;
+using Microsoft.Win32;
+using SPTInstaller.Models;
 
-namespace SPTInstaller.Aki.Helper
+namespace SPTInstaller.Helpers;
+
+public static class PreCheckHelper
 {
-    public static class PreCheckHelper
+    private const string registryInstall = @"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\EscapeFromTarkov";
+
+    public static string DetectOriginalGamePath()
     {
-        private const string registryInstall = @"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\EscapeFromTarkov";
+        // We can't detect the installed path on non-Windows
+        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            return null;
 
-        public static string DetectOriginalGamePath()
+        var uninstallStringValue = Registry.LocalMachine.OpenSubKey(registryInstall, false)
+            ?.GetValue("UninstallString");
+        var info = (uninstallStringValue is string key) ? new FileInfo(key) : null;
+
+        return info?.DirectoryName;
+    }
+
+    public static Result DetectOriginalGameVersion(string gamePath)
+    {
+        try
         {
-            // We can't detect the installed path on non-Windows
-            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
-                return null;
-
-            var uninstallStringValue = Registry.LocalMachine.OpenSubKey(registryInstall, false)
-                ?.GetValue("UninstallString");
-            var info = (uninstallStringValue is string key) ? new FileInfo(key) : null;
-
-            return info?.DirectoryName;
+            string version = FileVersionInfo.GetVersionInfo(Path.Join(gamePath + "/EscapeFromTarkov.exe")).ProductVersion.Replace('-', '.').Split('.')[^2];
+            return Result.FromSuccess(version);
         }
-
-        public static Result DetectOriginalGameVersion(string gamePath)
+        catch (Exception ex)
         {
-            try
-            {
-                string version = FileVersionInfo.GetVersionInfo(Path.Join(gamePath + "/EscapeFromTarkov.exe")).ProductVersion.Replace('-', '.').Split('.')[^2];
-                return Result.FromSuccess(version);
-            }
-            catch (Exception ex)
-            {
-                return Result.FromError($"File not found: {ex.Message}");
-            }
+            return Result.FromError($"File not found: {ex.Message}");
         }
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/Helpers/ProcessHelper.cs b/SPTInstaller/Helpers/ProcessHelper.cs
index a2c6e9a..63be9dc 100644
--- a/SPTInstaller/Helpers/ProcessHelper.cs
+++ b/SPTInstaller/Helpers/ProcessHelper.cs
@@ -1,61 +1,60 @@
-using SPTInstaller.Models;
-using System.Diagnostics;
-using System.IO;
+using System.Diagnostics;
+using SPTInstaller.Models;
 
-namespace SPTInstaller.Aki.Helper
+namespace SPTInstaller.Helpers;
+
+public enum PatcherExitCode
 {
-    public enum PatcherExitCode
-    {
-        ProgramClosed = 0,
-        Success = 10,
-        EftExeNotFound = 11,
-        NoPatchFolder = 12,
-        MissingFile = 13,
-        MissingDir = 14,
-        PatchFailed = 15
-    }
+    ProgramClosed = 0,
+    Success = 10,
+    EftExeNotFound = 11,
+    NoPatchFolder = 12,
+    MissingFile = 13,
+    MissingDir = 14,
+    PatchFailed = 15
+}
 
-    public static class ProcessHelper
+public static class ProcessHelper
+{
+    public static Result PatchClientFiles(FileInfo executable, DirectoryInfo workingDir)
     {
-        public static Result PatchClientFiles(FileInfo executable, DirectoryInfo workingDir)
+        if (!executable.Exists || !workingDir.Exists)
         {
-            if (!executable.Exists || !workingDir.Exists)
-            {
-                return Result.FromError($"Could not find executable ({executable.Name}) or working directory ({workingDir.Name})");
-            }
+            return Result.FromError(
+                $"Could not find executable ({executable.Name}) or working directory ({workingDir.Name})");
+        }
 
-            var process = new Process();
-            process.StartInfo.FileName = executable.FullName;
-            process.StartInfo.WorkingDirectory = workingDir.FullName;
-            process.EnableRaisingEvents = true;
-            process.StartInfo.Arguments = "autoclose";
-            process.Start();
+        var process = new Process();
+        process.StartInfo.FileName = executable.FullName;
+        process.StartInfo.WorkingDirectory = workingDir.FullName;
+        process.EnableRaisingEvents = true;
+        process.StartInfo.Arguments = "autoclose";
+        process.Start();
 
-            process.WaitForExit();
+        process.WaitForExit();
 
-            switch ((PatcherExitCode)process.ExitCode)
-            {
-                case PatcherExitCode.Success:
-                    return Result.FromSuccess("Patcher Finished Successfully, extracting Aki");
+        switch ((PatcherExitCode)process.ExitCode)
+        {
+            case PatcherExitCode.Success:
+                return Result.FromSuccess("Patcher Finished Successfully, extracting Aki");
 
-                case PatcherExitCode.ProgramClosed:
-                    return Result.FromError("Patcher was closed before completing!");
+            case PatcherExitCode.ProgramClosed:
+                return Result.FromError("Patcher was closed before completing!");
 
-                case PatcherExitCode.EftExeNotFound:
-                    return Result.FromError("EscapeFromTarkov.exe is missing from the install Path");
+            case PatcherExitCode.EftExeNotFound:
+                return Result.FromError("EscapeFromTarkov.exe is missing from the install Path");
 
-                case PatcherExitCode.NoPatchFolder:
-                    return Result.FromError("Patchers Folder called 'Aki_Patches' is missing");
+            case PatcherExitCode.NoPatchFolder:
+                return Result.FromError("Patchers Folder called 'Aki_Patches' is missing");
 
-                case PatcherExitCode.MissingFile:
-                    return Result.FromError("EFT files was missing a Vital file to continue");
+            case PatcherExitCode.MissingFile:
+                return Result.FromError("EFT files was missing a Vital file to continue");
 
-                case PatcherExitCode.PatchFailed:
-                    return Result.FromError("A patch failed to apply");
+            case PatcherExitCode.PatchFailed:
+                return Result.FromError("A patch failed to apply");
 
-                default:
-                    return Result.FromError("an unknown error occurred in the patcher");
-            }
+            default:
+                return Result.FromError("an unknown error occurred in the patcher");
         }
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/Helpers/ServiceHelper.cs b/SPTInstaller/Helpers/ServiceHelper.cs
index e17b8ed..021eb26 100644
--- a/SPTInstaller/Helpers/ServiceHelper.cs
+++ b/SPTInstaller/Helpers/ServiceHelper.cs
@@ -1,129 +1,127 @@
 using Serilog;
 using Splat;
-using System;
 using System.Collections.Generic;
 using System.Linq;
 
-namespace SPTInstaller.Helpers
+namespace SPTInstaller.Helpers;
+
+/// <summary>
+/// A helper class to handle simple service registration to Splat with constructor parameter injection
+/// </summary>
+/// <remarks>Splat only recognizes the registered types and doesn't account for interfaces :(</remarks>
+internal static class ServiceHelper
 {
-    /// <summary>
-    /// A helper class to handle simple service registration to Splat with constructor parameter injection
-    /// </summary>
-    /// <remarks>Splat only recognizes the registered types and doesn't account for interfaces :(</remarks>
-    internal static class ServiceHelper
+    private static bool TryRegisterInstance<T, T2>(object[] parameters = null)
     {
-        private static bool TryRegisterInstance<T, T2>(object[] parameters = null)
+        var instance = Activator.CreateInstance(typeof(T2), parameters);
+
+        if (instance != null)
         {
-            var instance = Activator.CreateInstance(typeof(T2), parameters);
-
-            if (instance != null)
-            {
-                Locator.CurrentMutable.RegisterConstant<T>((T)instance);
-                return true;
-            }
-
-            return false;
+            Locator.CurrentMutable.RegisterConstant<T>((T)instance);
+            return true;
         }
 
-        /// <summary>
-        /// Register a class as a service
-        /// </summary>
-        /// <typeparam name="T">class to register</typeparam>
-        public static void Register<T>() where T : class => Register<T, T>();
+        return false;
+    }
 
-        /// <summary>
-        /// Register a class as a service by another type
-        /// </summary>
-        /// <typeparam name="T">type to register as</typeparam>
-        /// <typeparam name="T2">class to register</typeparam>
-        public static void Register<T, T2>() where T : class
+    /// <summary>
+    /// Register a class as a service
+    /// </summary>
+    /// <typeparam name="T">class to register</typeparam>
+    public static void Register<T>() where T : class => Register<T, T>();
+
+    /// <summary>
+    /// Register a class as a service by another type
+    /// </summary>
+    /// <typeparam name="T">type to register as</typeparam>
+    /// <typeparam name="T2">class to register</typeparam>
+    public static void Register<T, T2>() where T : class
+    {
+        var constructors = typeof(T2).GetConstructors();
+
+        foreach(var constructor in constructors)
         {
-            var constructors = typeof(T2).GetConstructors();
+            var parmesan = constructor.GetParameters();
 
-            foreach(var constructor in constructors)
+            if(parmesan.Length == 0)
             {
-                var parmesan = constructor.GetParameters();
+                if (TryRegisterInstance<T, T2>()) return;
 
-                if(parmesan.Length == 0)
-                {
-                    if (TryRegisterInstance<T, T2>()) return;
+                continue;
+            }
 
-                    continue;
-                }
+            List<object> parameters = new List<object>();
 
-                List<object> parameters = new List<object>();
-
-                for(int i = 0; i < parmesan.Length; i++)
-                {
-                    var parm = parmesan[i];
+            for(int i = 0; i < parmesan.Length; i++)
+            {
+                var parm = parmesan[i];
                     
-                    var parmValue = Get(parm.ParameterType);
+                var parmValue = Get(parm.ParameterType);
 
-                    if (parmValue != null) parameters.Add(parmValue);
-                }
-
-                if (TryRegisterInstance<T, T2>(parameters.ToArray())) return;
-            }
-        }
-
-        /// <summary>
-        /// Get a service from splat
-        /// </summary>
-        /// <param name="type"></param>
-        /// <returns></returns>
-        /// <exception cref="InvalidOperationException">Thrown if the service isn't found</exception>
-        public static object Get(Type type)
-        {
-            var service = Locator.Current.GetService(type);
-
-            if (service == null)
-            {
-                var message = $"Could not locate service of type '{type.Name}'";
-                Log.Error(message);
-                throw new InvalidOperationException(message);
+                if (parmValue != null) parameters.Add(parmValue);
             }
 
-            return service;
-        }
-
-        /// <summary>
-        /// Get a service from splat
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <returns></returns>
-        /// <exception cref="InvalidOperationException">Thrown if the service isn't found</exception>
-        public static T Get<T>()
-        {
-            var service = Locator.Current.GetService<T>();
-
-            if (service == null)
-            {
-                var message = $"Could not locate service of type '{nameof(T)}'";
-                Log.Error(message);
-                throw new InvalidOperationException(message);
-            }
-
-            return service;
-        }
-
-        /// <summary>
-        /// Get all services of a type
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <returns></returns>
-        /// <exception cref="InvalidOperationException">thrown if no services are found</exception>
-        public static T[] GetAll<T>()
-        {
-            var services = Locator.Current.GetServices<T>().ToArray();
-
-            if (services == null || services.Count() == 0)
-            {
-                var message = $"Could not locate service of type '{nameof(T)}'";
-                Log.Error(message);
-                throw new InvalidOperationException(message);
-            }
-
-            return services;
+            if (TryRegisterInstance<T, T2>(parameters.ToArray())) return;
         }
     }
-}
+
+    /// <summary>
+    /// Get a service from splat
+    /// </summary>
+    /// <param name="type"></param>
+    /// <returns></returns>
+    /// <exception cref="InvalidOperationException">Thrown if the service isn't found</exception>
+    public static object Get(Type type)
+    {
+        var service = Locator.Current.GetService(type);
+
+        if (service == null)
+        {
+            var message = $"Could not locate service of type '{type.Name}'";
+            Log.Error(message);
+            throw new InvalidOperationException(message);
+        }
+
+        return service;
+    }
+
+    /// <summary>
+    /// Get a service from splat
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <returns></returns>
+    /// <exception cref="InvalidOperationException">Thrown if the service isn't found</exception>
+    public static T Get<T>()
+    {
+        var service = Locator.Current.GetService<T>();
+
+        if (service == null)
+        {
+            var message = $"Could not locate service of type '{nameof(T)}'";
+            Log.Error(message);
+            throw new InvalidOperationException(message);
+        }
+
+        return service;
+    }
+
+    /// <summary>
+    /// Get all services of a type
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <returns></returns>
+    /// <exception cref="InvalidOperationException">thrown if no services are found</exception>
+    public static T[] GetAll<T>()
+    {
+        var services = Locator.Current.GetServices<T>().ToArray();
+
+        if (services == null || services.Count() == 0)
+        {
+            var message = $"Could not locate service of type '{nameof(T)}'";
+            Log.Error(message);
+            throw new InvalidOperationException(message);
+        }
+
+        return services;
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Helpers/ZipHelper.cs b/SPTInstaller/Helpers/ZipHelper.cs
index 4462ae5..5b970f9 100644
--- a/SPTInstaller/Helpers/ZipHelper.cs
+++ b/SPTInstaller/Helpers/ZipHelper.cs
@@ -1,56 +1,53 @@
-using SharpCompress.Archives;
+using System.Linq;
+using SharpCompress.Archives;
 using SharpCompress.Archives.Zip;
 using SharpCompress.Common;
 using SPTInstaller.Models;
-using System;
-using System.IO;
-using System.Linq;
 
-namespace SPTInstaller.Aki.Helper
+namespace SPTInstaller.Helpers;
+
+public static class ZipHelper
 {
-    public static class ZipHelper
+    public static Result Decompress(FileInfo ArchivePath, DirectoryInfo OutputFolderPath, IProgress<double> progress = null)
     {
-        public static Result Decompress(FileInfo ArchivePath, DirectoryInfo OutputFolderPath, IProgress<double> progress = null)
+        try
         {
-            try
+            OutputFolderPath.Refresh();
+
+            if (!OutputFolderPath.Exists) OutputFolderPath.Create();
+
+            using var archive = ZipArchive.Open(ArchivePath);
+            var totalEntries = archive.Entries.Where(entry => !entry.IsDirectory);
+            var processedEntries = 0;
+
+            foreach (var entry in totalEntries)
             {
-                OutputFolderPath.Refresh();
-
-                if (!OutputFolderPath.Exists) OutputFolderPath.Create();
-
-                using var archive = ZipArchive.Open(ArchivePath);
-                var totalEntries = archive.Entries.Where(entry => !entry.IsDirectory);
-                int processedEntries = 0;
-
-                foreach (var entry in totalEntries)
+                entry.WriteToDirectory(OutputFolderPath.FullName, new ExtractionOptions()
                 {
-                    entry.WriteToDirectory(OutputFolderPath.FullName, new ExtractionOptions()
-                    {
-                        ExtractFullPath = true,
-                        Overwrite = true
-                    });
+                    ExtractFullPath = true,
+                    Overwrite = true
+                });
 
-                    processedEntries++;
+                processedEntries++;
 
-                    if (progress != null)
-                    {
-                        progress.Report(Math.Floor(((double)processedEntries / totalEntries.Count()) * 100));
-                    }
-                }
-
-                OutputFolderPath.Refresh();
-
-                if (!OutputFolderPath.Exists)
+                if (progress != null)
                 {
-                    return Result.FromError($"Failed to extract files: {ArchivePath.Name}");
+                    progress.Report(Math.Floor(((double)processedEntries / totalEntries.Count()) * 100));
                 }
-
-                return Result.FromSuccess();
             }
-            catch (Exception ex)
+
+            OutputFolderPath.Refresh();
+
+            if (!OutputFolderPath.Exists)
             {
-                return Result.FromError(ex.Message);
+                return Result.FromError($"Failed to extract files: {ArchivePath.Name}");
             }
+
+            return Result.FromSuccess();
+        }
+        catch (Exception ex)
+        {
+            return Result.FromError(ex.Message);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/CopyClientTask.cs b/SPTInstaller/Installer Tasks/CopyClientTask.cs
index 1783959..646677a 100644
--- a/SPTInstaller/Installer Tasks/CopyClientTask.cs	
+++ b/SPTInstaller/Installer Tasks/CopyClientTask.cs	
@@ -1,30 +1,26 @@
-using Serilog;
-using SPTInstaller.Aki.Helper;
-using SPTInstaller.Interfaces;
+using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
-using System;
-using System.IO;
 using System.Threading.Tasks;
+using SPTInstaller.Helpers;
 
-namespace SPTInstaller.Installer_Tasks
+namespace SPTInstaller.Installer_Tasks;
+
+public class CopyClientTask : InstallerTaskBase
 {
-    public class CopyClientTask : InstallerTaskBase
+    private InternalData _data;
+
+    public CopyClientTask(InternalData data) : base("Copy Client Files")
     {
-        private InternalData _data;
-
-        public CopyClientTask(InternalData data) : base("Copy Client Files")
-        {
-            _data = data;
-        }
-
-        public override async Task<IResult> TaskOperation()
-        {
-            SetStatus("Copying Client Files", "", 0);
-
-            var originalGameDirInfo = new DirectoryInfo(_data.OriginalGamePath);
-            var targetInstallDirInfo = new DirectoryInfo(_data.TargetInstallPath);
-
-            return FileHelper.CopyDirectoryWithProgress(originalGameDirInfo, targetInstallDirInfo, (message, progress) => { SetStatus(null, message, progress, null, true); });
-        }
+        _data = data;
     }
-}
+
+    public override async Task<IResult> TaskOperation()
+    {
+        SetStatus("Copying Client Files", "", 0);
+
+        var originalGameDirInfo = new DirectoryInfo(_data.OriginalGamePath);
+        var targetInstallDirInfo = new DirectoryInfo(_data.TargetInstallPath);
+
+        return FileHelper.CopyDirectoryWithProgress(originalGameDirInfo, targetInstallDirInfo, (message, progress) => { SetStatus(null, message, progress, null, true); });
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/DownloadTask.cs b/SPTInstaller/Installer Tasks/DownloadTask.cs
index 8a91e2e..15e651b 100644
--- a/SPTInstaller/Installer Tasks/DownloadTask.cs	
+++ b/SPTInstaller/Installer Tasks/DownloadTask.cs	
@@ -1,126 +1,123 @@
 using CG.Web.MegaApiClient;
 using Newtonsoft.Json;
-using SPTInstaller.Aki.Helper;
 using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
-using System;
 using System.Collections.Generic;
-using System.IO;
 using System.Threading.Tasks;
+using SPTInstaller.Helpers;
 
-namespace SPTInstaller.Installer_Tasks
+namespace SPTInstaller.Installer_Tasks;
+
+public class DownloadTask : InstallerTaskBase
 {
-    public class DownloadTask : InstallerTaskBase
+    private InternalData _data;
+
+    public DownloadTask(InternalData data) : base("Download Files")
     {
-        private InternalData _data;
+        _data = data;
+    }
 
-        public DownloadTask(InternalData data) : base("Download Files")
+    private async Task<IResult> BuildMirrorList()
+    {
+        var progress = new Progress<double>((d) => { SetStatus("Downloading Mirror List", "", (int)Math.Floor(d));});
+
+        var file = await DownloadCacheHelper.GetOrDownloadFileAsync("mirrors.json", _data.PatcherMirrorsLink, progress);
+
+        if (file == null)
         {
-            _data = data;
+            return Result.FromError("Failed to download mirror list");
         }
 
-        private async Task<IResult> BuildMirrorList()
+        var mirrorsList = JsonConvert.DeserializeObject<List<DownloadMirror>>(File.ReadAllText(file.FullName));
+
+        if (mirrorsList is List<DownloadMirror> mirrors)
         {
-            var progress = new Progress<double>((d) => { SetStatus("Downloading Mirror List", "", (int)Math.Floor(d));});
-
-            var file = await DownloadCacheHelper.GetOrDownloadFileAsync("mirrors.json", _data.PatcherMirrorsLink, progress);
-
-            if (file == null)
-            {
-                return Result.FromError("Failed to download mirror list");
-            }
-
-            var mirrorsList = JsonConvert.DeserializeObject<List<DownloadMirror>>(File.ReadAllText(file.FullName));
-
-            if (mirrorsList is List<DownloadMirror> mirrors)
-            {
-                _data.PatcherReleaseMirrors = mirrors;
-
-                return Result.FromSuccess();
-            }
-
-            return Result.FromError("Failed to deserialize mirrors list");
-        }
-
-        private async Task<IResult> DownloadPatcherFromMirrors(IProgress<double> progress)
-        {
-            foreach (var mirror in _data.PatcherReleaseMirrors)
-            {
-                SetStatus($"Downloading Patcher", mirror.Link);
-
-                // mega is a little weird since they use encryption, but thankfully there is a great library for their api :)
-                if (mirror.Link.StartsWith("https://mega"))
-                {
-                    var megaClient = new MegaApiClient();
-                    await megaClient.LoginAnonymousAsync();
-
-                    // if mega fails to connect, try the next mirror
-                    if (!megaClient.IsLoggedIn) continue;
-
-                    try
-                    {
-                        using var megaDownloadStream = await megaClient.DownloadAsync(new Uri(mirror.Link), progress);
-
-                        _data.PatcherZipInfo = await DownloadCacheHelper.GetOrDownloadFileAsync("patcher.zip", megaDownloadStream, mirror.Hash);
-
-                        if(_data.PatcherZipInfo == null)
-                        {
-                            continue;
-                        }
-
-                        return Result.FromSuccess();
-                    }
-                    catch
-                    {
-                        //most likely a 509 (Bandwidth limit exceeded) due to mega's user quotas.
-                        continue;
-                    }
-                }
-
-                _data.PatcherZipInfo = await DownloadCacheHelper.GetOrDownloadFileAsync("patcher.zip", mirror.Link, progress, mirror.Hash);
-
-                if (_data.PatcherZipInfo != null)
-                {
-                    return Result.FromSuccess();
-                }
-            }
-
-            return Result.FromError("Failed to download Patcher");
-        }
-
-        public override async Task<IResult> TaskOperation()
-        {
-            var progress = new Progress<double>((d) => { SetStatus(null, null, (int)Math.Floor(d)); });
-
-            if (_data.PatchNeeded)
-            {
-                var buildResult = await BuildMirrorList();
-
-                if (!buildResult.Succeeded)
-                {
-                    return buildResult;
-                }
-
-                SetStatus(null, null, 0);
-
-                var patcherDownloadRresult = await DownloadPatcherFromMirrors(progress);
-
-                if (!patcherDownloadRresult.Succeeded)
-                {
-                    return patcherDownloadRresult;
-                }
-            }
-
-            SetStatus("Downloading SPT-AKI", _data.AkiReleaseDownloadLink, 0);
-
-            _data.AkiZipInfo = await DownloadCacheHelper.GetOrDownloadFileAsync("sptaki.zip", _data.AkiReleaseDownloadLink, progress, _data.AkiReleaseHash);
-
-            if (_data.AkiZipInfo == null)
-            {
-                return Result.FromError("Failed to download spt-aki");
-            }
+            _data.PatcherReleaseMirrors = mirrors;
 
             return Result.FromSuccess();
         }
+
+        return Result.FromError("Failed to deserialize mirrors list");
+    }
+
+    private async Task<IResult> DownloadPatcherFromMirrors(IProgress<double> progress)
+    {
+        foreach (var mirror in _data.PatcherReleaseMirrors)
+        {
+            SetStatus($"Downloading Patcher", mirror.Link);
+
+            // mega is a little weird since they use encryption, but thankfully there is a great library for their api :)
+            if (mirror.Link.StartsWith("https://mega"))
+            {
+                var megaClient = new MegaApiClient();
+                await megaClient.LoginAnonymousAsync();
+
+                // if mega fails to connect, try the next mirror
+                if (!megaClient.IsLoggedIn) continue;
+
+                try
+                {
+                    using var megaDownloadStream = await megaClient.DownloadAsync(new Uri(mirror.Link), progress);
+
+                    _data.PatcherZipInfo = await DownloadCacheHelper.GetOrDownloadFileAsync("patcher.zip", megaDownloadStream, mirror.Hash);
+
+                    if(_data.PatcherZipInfo == null)
+                    {
+                        continue;
+                    }
+
+                    return Result.FromSuccess();
+                }
+                catch
+                {
+                    //most likely a 509 (Bandwidth limit exceeded) due to mega's user quotas.
+                    continue;
+                }
+            }
+
+            _data.PatcherZipInfo = await DownloadCacheHelper.GetOrDownloadFileAsync("patcher.zip", mirror.Link, progress, mirror.Hash);
+
+            if (_data.PatcherZipInfo != null)
+            {
+                return Result.FromSuccess();
+            }
+        }
+
+        return Result.FromError("Failed to download Patcher");
+    }
+
+    public override async Task<IResult> TaskOperation()
+    {
+        var progress = new Progress<double>((d) => { SetStatus(null, null, (int)Math.Floor(d)); });
+
+        if (_data.PatchNeeded)
+        {
+            var buildResult = await BuildMirrorList();
+
+            if (!buildResult.Succeeded)
+            {
+                return buildResult;
+            }
+
+            SetStatus(null, null, 0);
+
+            var patcherDownloadRresult = await DownloadPatcherFromMirrors(progress);
+
+            if (!patcherDownloadRresult.Succeeded)
+            {
+                return patcherDownloadRresult;
+            }
+        }
+
+        SetStatus("Downloading SPT-AKI", _data.AkiReleaseDownloadLink, 0);
+
+        _data.AkiZipInfo = await DownloadCacheHelper.GetOrDownloadFileAsync("sptaki.zip", _data.AkiReleaseDownloadLink, progress, _data.AkiReleaseHash);
+
+        if (_data.AkiZipInfo == null)
+        {
+            return Result.FromError("Failed to download spt-aki");
+        }
+
+        return Result.FromSuccess();
     }
 }
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/IntializationTask.cs b/SPTInstaller/Installer Tasks/IntializationTask.cs
index 28dae32..a39c238 100644
--- a/SPTInstaller/Installer Tasks/IntializationTask.cs	
+++ b/SPTInstaller/Installer Tasks/IntializationTask.cs	
@@ -1,59 +1,58 @@
-using SPTInstaller.Aki.Helper;
-using SPTInstaller.Interfaces;
+using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
 using System.Threading.Tasks;
+using SPTInstaller.Helpers;
 
-namespace SPTInstaller.Installer_Tasks
+namespace SPTInstaller.Installer_Tasks;
+
+public class InitializationTask : InstallerTaskBase
 {
-    public class InitializationTask : InstallerTaskBase
+    private InternalData _data;
+
+    public InitializationTask(InternalData data) : base("Startup")
     {
-        private InternalData _data;
-
-        public InitializationTask(InternalData data) : base("Startup")
-        {
-            _data = data;
-        }
-
-        public override async Task<IResult> TaskOperation()
-        {
-            SetStatus("Initializing", $"Target Install Path: {FileHelper.GetRedactedPath(_data.TargetInstallPath)}");
-
-            _data.OriginalGamePath = PreCheckHelper.DetectOriginalGamePath();
-
-            if (_data.OriginalGamePath == null)
-            {
-                return Result.FromError("EFT IS NOT INSTALLED!");
-            }
-
-            SetStatus(null, $"Installed EFT Game Path: {FileHelper.GetRedactedPath(_data.OriginalGamePath)}");
-
-            var result = PreCheckHelper.DetectOriginalGameVersion(_data.OriginalGamePath);
-
-            if (!result.Succeeded)
-            {
-                return result;
-            }
-
-            _data.OriginalGameVersion = result.Message;
-
-            SetStatus(null, $"Installed EFT Game Version: {_data.OriginalGameVersion}");
-
-            if (_data.OriginalGamePath == null)
-            {
-                return Result.FromError("Unable to find original EFT directory, please make sure EFT is installed. Please also run EFT once");
-            }
-
-            if (_data.OriginalGamePath == _data.TargetInstallPath)
-            {
-                return Result.FromError("Installer is located in EFT's original directory. Please move the installer to a seperate folder as per the guide");
-            }
-
-            if (File.Exists(Path.Join(_data.TargetInstallPath, "EscapeFromTarkov.exe")))
-            {
-                return Result.FromError("Installer is located in a folder that has existing game files. Please make sure the installer is in a fresh folder as per the guide");
-            }
-
-            return Result.FromSuccess($"Current Game Version: {_data.OriginalGameVersion}");
-        }
+        _data = data;
     }
-}
+
+    public override async Task<IResult> TaskOperation()
+    {
+        SetStatus("Initializing", $"Target Install Path: {FileHelper.GetRedactedPath(_data.TargetInstallPath)}");
+
+        _data.OriginalGamePath = PreCheckHelper.DetectOriginalGamePath();
+
+        if (_data.OriginalGamePath == null)
+        {
+            return Result.FromError("EFT IS NOT INSTALLED!");
+        }
+
+        SetStatus(null, $"Installed EFT Game Path: {FileHelper.GetRedactedPath(_data.OriginalGamePath)}");
+
+        var result = PreCheckHelper.DetectOriginalGameVersion(_data.OriginalGamePath);
+
+        if (!result.Succeeded)
+        {
+            return result;
+        }
+
+        _data.OriginalGameVersion = result.Message;
+
+        SetStatus(null, $"Installed EFT Game Version: {_data.OriginalGameVersion}");
+
+        if (_data.OriginalGamePath == null)
+        {
+            return Result.FromError("Unable to find original EFT directory, please make sure EFT is installed. Please also run EFT once");
+        }
+
+        if (_data.OriginalGamePath == _data.TargetInstallPath)
+        {
+            return Result.FromError("Installer is located in EFT's original directory. Please move the installer to a seperate folder as per the guide");
+        }
+
+        if (File.Exists(Path.Join(_data.TargetInstallPath, "EscapeFromTarkov.exe")))
+        {
+            return Result.FromError("Installer is located in a folder that has existing game files. Please make sure the installer is in a fresh folder as per the guide");
+        }
+
+        return Result.FromSuccess($"Current Game Version: {_data.OriginalGameVersion}");
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/PreChecks/NetCore6PreCheck.cs b/SPTInstaller/Installer Tasks/PreChecks/NetCore6PreCheck.cs
index fa6ffdd..eb7c763 100644
--- a/SPTInstaller/Installer Tasks/PreChecks/NetCore6PreCheck.cs	
+++ b/SPTInstaller/Installer Tasks/PreChecks/NetCore6PreCheck.cs	
@@ -1,58 +1,56 @@
 using SPTInstaller.Models;
-using System;
 using System.Diagnostics;
 using System.Threading.Tasks;
 
-namespace SPTInstaller.Installer_Tasks.PreChecks
+namespace SPTInstaller.Installer_Tasks.PreChecks;
+
+public class NetCore6PreCheck : PreCheckBase
 {
-    public class NetCore6PreCheck : PreCheckBase
+    public NetCore6PreCheck() : base(".Net Core 6 Desktop Runtime", false)
     {
-        public NetCore6PreCheck() : base(".Net Core 6 Desktop Runtime", false)
+    }
+
+    public override async Task<bool> CheckOperation()
+    {
+        var minRequiredVersion = new Version("6.0.0");
+        string[] output;
+
+        try
         {
+            var proc = Process.Start(new ProcessStartInfo()
+            {
+                FileName = "dotnet",
+                Arguments = "--list-runtimes",
+                RedirectStandardOutput = true,
+                CreateNoWindow = true
+            });
+
+            proc.WaitForExit();
+
+            output = proc.StandardOutput.ReadToEnd().Split("\r\n");
         }
-
-        public override async Task<bool> CheckOperation()
+        catch (Exception ex)
         {
-            var minRequiredVersion = new Version("6.0.0");
-            string[] output;
-
-            try
-            {
-                var proc = Process.Start(new ProcessStartInfo()
-                {
-                    FileName = "dotnet",
-                    Arguments = "--list-runtimes",
-                    RedirectStandardOutput = true,
-                    CreateNoWindow = true
-                });
-
-                proc.WaitForExit();
-
-                output = proc.StandardOutput.ReadToEnd().Split("\r\n");
-            }
-            catch (Exception ex)
-            {
-                // TODO: logging
-                return false;
-            }
-
-            foreach (var lineVersion in output)
-            {
-                if (lineVersion.StartsWith("Microsoft.WindowsDesktop.App") && lineVersion.Split(" ").Length > 1)
-                {
-                    string stringVerion = lineVersion.Split(" ")[1];
-
-                    var foundVersion = new Version(stringVerion);
-
-                    // not fully sure if we should only check for 6.x.x versions or if higher major versions are ok -waffle
-                    if (foundVersion >= minRequiredVersion)
-                    {
-                        return true;
-                    }
-                }
-            }
-
+            // TODO: logging
             return false;
         }
+
+        foreach (var lineVersion in output)
+        {
+            if (lineVersion.StartsWith("Microsoft.WindowsDesktop.App") && lineVersion.Split(" ").Length > 1)
+            {
+                string stringVerion = lineVersion.Split(" ")[1];
+
+                var foundVersion = new Version(stringVerion);
+
+                // not fully sure if we should only check for 6.x.x versions or if higher major versions are ok -waffle
+                if (foundVersion >= minRequiredVersion)
+                {
+                    return true;
+                }
+            }
+        }
+
+        return false;
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/PreChecks/NetFramework472PreCheck.cs b/SPTInstaller/Installer Tasks/PreChecks/NetFramework472PreCheck.cs
index f190460..55c8160 100644
--- a/SPTInstaller/Installer Tasks/PreChecks/NetFramework472PreCheck.cs	
+++ b/SPTInstaller/Installer Tasks/PreChecks/NetFramework472PreCheck.cs	
@@ -1,46 +1,44 @@
 using Microsoft.Win32;
 using SPTInstaller.Models;
-using System;
 using System.Threading.Tasks;
 
-namespace SPTInstaller.Installer_Tasks.PreChecks
+namespace SPTInstaller.Installer_Tasks.PreChecks;
+
+public class NetFramework472PreCheck : PreCheckBase
 {
-    public class NetFramework472PreCheck : PreCheckBase
+    public NetFramework472PreCheck() : base(".Net Framework 4.7.2", false)
     {
-        public NetFramework472PreCheck() : base(".Net Framework 4.7.2", false)
+    }
+
+    public override async Task<bool> CheckOperation()
+    {
+        try
         {
+            var minRequiredVersion = new Version("4.7.2");
+
+            var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full");
+
+            if (key == null)
+            {
+                return false;
+            }
+
+            var value = key.GetValue("Version");
+
+            if (value != null && value is string versionString)
+            {
+                var installedVersion = new Version(versionString);
+
+                return installedVersion > minRequiredVersion;
+            }
+
+            return false;
         }
-
-        public override async Task<bool> CheckOperation()
+        catch (Exception ex)
         {
-            try
-            {
-                var minRequiredVersion = new Version("4.7.2");
+            // TODO: log exceptions
 
-                var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full");
-
-                if (key == null)
-                {
-                    return false;
-                }
-
-                var value = key.GetValue("Version");
-
-                if (value != null && value is string versionString)
-                {
-                    var installedVersion = new Version(versionString);
-
-                    return installedVersion > minRequiredVersion;
-                }
-
-                return false;
-            }
-            catch (Exception ex)
-            {
-                // TODO: log exceptions
-
-                return false;
-            }
+            return false;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs b/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs
index edddeda..e28b14e 100644
--- a/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs	
+++ b/SPTInstaller/Installer Tasks/ReleaseCheckTask.cs	
@@ -1,89 +1,87 @@
 using Gitea.Api;
 using Gitea.Client;
-using SPTInstaller.Aki.Helper;
 using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
-using System;
 using System.Threading.Tasks;
+using SPTInstaller.Helpers;
 
-namespace SPTInstaller.Installer_Tasks
+namespace SPTInstaller.Installer_Tasks;
+
+public class ReleaseCheckTask : InstallerTaskBase
 {
-    public class ReleaseCheckTask : InstallerTaskBase
+    private InternalData _data;
+
+    public ReleaseCheckTask(InternalData data) : base("Release Checks")
     {
-        private InternalData _data;
+        _data = data;
+    }
 
-        public ReleaseCheckTask(InternalData data) : base("Release Checks")
+    public override async Task<IResult> TaskOperation()
+    {
+        try
         {
-            _data = data;
+            Configuration.Default.BasePath = "https://dev.sp-tarkov.com/api/v1";
+
+            var repo = new RepositoryApi(Configuration.Default);
+
+            SetStatus("Checking SPT Releases", "", null, ProgressStyle.Indeterminate);
+
+            var akiRepoReleases = await repo.RepoListReleasesAsync("SPT-AKI", "Stable-releases");
+
+            SetStatus("Checking for Patches", "", null, ProgressStyle.Indeterminate);
+
+            var patchRepoReleases = await repo.RepoListReleasesAsync("SPT-AKI", "Downgrade-Patches");
+
+            var latestAkiRelease = akiRepoReleases.FindAll(x => !x.Prerelease)[0];
+            var latestAkiVersion = latestAkiRelease.Name.Replace('(', ' ').Replace(')', ' ').Split(' ')[3];
+            var comparePatchToAki = patchRepoReleases?.Find(x => x.Name.Contains(_data.OriginalGameVersion) && x.Name.Contains(latestAkiVersion));
+
+            _data.PatcherMirrorsLink = comparePatchToAki?.Assets[0].BrowserDownloadUrl;
+            _data.AkiReleaseDownloadLink = latestAkiRelease.Assets[0].BrowserDownloadUrl;
+            _data.AkiReleaseHash = FileHashHelper.GetGiteaReleaseHash(latestAkiRelease);
+
+            int IntAkiVersion = int.Parse(latestAkiVersion);
+            int IntGameVersion = int.Parse(_data.OriginalGameVersion);
+            bool patchNeedCheck = false;
+
+            if (IntGameVersion > IntAkiVersion)
+            {
+                patchNeedCheck = true;
+            }
+
+            if (IntGameVersion < IntAkiVersion)
+            {
+                return Result.FromError("Your client is outdated. Please update EFT");
+
+            }
+
+            if (IntGameVersion == IntAkiVersion)
+            {
+                patchNeedCheck = false;
+            }
+
+            if (comparePatchToAki == null && patchNeedCheck)
+            {
+                return Result.FromError("No patcher available for your version");
+            }
+
+            _data.PatchNeeded = patchNeedCheck;
+
+            string status = $"Current Release: {latestAkiVersion}";
+
+            if (_data.PatchNeeded)
+            {
+                status += " - Patch Available";
+            }
+
+            SetStatus(null, status);
+
+            return Result.FromSuccess(status);
         }
-
-        public override async Task<IResult> TaskOperation()
+        catch (Exception ex)
         {
-            try
-            {
-                Configuration.Default.BasePath = "https://dev.sp-tarkov.com/api/v1";
-
-                var repo = new RepositoryApi(Configuration.Default);
-
-                SetStatus("Checking SPT Releases", "", null, ProgressStyle.Indeterminate);
-
-                var akiRepoReleases = await repo.RepoListReleasesAsync("SPT-AKI", "Stable-releases");
-
-                SetStatus("Checking for Patches", "", null, ProgressStyle.Indeterminate);
-
-                var patchRepoReleases = await repo.RepoListReleasesAsync("SPT-AKI", "Downgrade-Patches");
-
-                var latestAkiRelease = akiRepoReleases.FindAll(x => !x.Prerelease)[0];
-                var latestAkiVersion = latestAkiRelease.Name.Replace('(', ' ').Replace(')', ' ').Split(' ')[3];
-                var comparePatchToAki = patchRepoReleases?.Find(x => x.Name.Contains(_data.OriginalGameVersion) && x.Name.Contains(latestAkiVersion));
-
-                _data.PatcherMirrorsLink = comparePatchToAki?.Assets[0].BrowserDownloadUrl;
-                _data.AkiReleaseDownloadLink = latestAkiRelease.Assets[0].BrowserDownloadUrl;
-                _data.AkiReleaseHash = FileHashHelper.GetGiteaReleaseHash(latestAkiRelease);
-
-                int IntAkiVersion = int.Parse(latestAkiVersion);
-                int IntGameVersion = int.Parse(_data.OriginalGameVersion);
-                bool patchNeedCheck = false;
-
-                if (IntGameVersion > IntAkiVersion)
-                {
-                    patchNeedCheck = true;
-                }
-
-                if (IntGameVersion < IntAkiVersion)
-                {
-                    return Result.FromError("Your client is outdated. Please update EFT");
-
-                }
-
-                if (IntGameVersion == IntAkiVersion)
-                {
-                    patchNeedCheck = false;
-                }
-
-                if (comparePatchToAki == null && patchNeedCheck)
-                {
-                    return Result.FromError("No patcher available for your version");
-                }
-
-                _data.PatchNeeded = patchNeedCheck;
-
-                string status = $"Current Release: {latestAkiVersion}";
-
-                if (_data.PatchNeeded)
-                {
-                    status += " - Patch Available";
-                }
-
-                SetStatus(null, status);
-
-                return Result.FromSuccess(status);
-            }
-            catch (Exception ex)
-            {
-                //request failed
-                return Result.FromError($"Request Failed:\n{ex.Message}");
-            }
+            //request failed
+            return Result.FromError($"Request Failed:\n{ex.Message}");
         }
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/SetupClientTask.cs b/SPTInstaller/Installer Tasks/SetupClientTask.cs
index e577659..e62e2f1 100644
--- a/SPTInstaller/Installer Tasks/SetupClientTask.cs	
+++ b/SPTInstaller/Installer Tasks/SetupClientTask.cs	
@@ -1,88 +1,85 @@
-using SPTInstaller.Aki.Helper;
-using SPTInstaller.Interfaces;
+using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
-using System;
-using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
+using SPTInstaller.Helpers;
 
-namespace SPTInstaller.Installer_Tasks
+namespace SPTInstaller.Installer_Tasks;
+
+public class SetupClientTask : InstallerTaskBase
 {
-    public class SetupClientTask : InstallerTaskBase
+    private InternalData _data;
+
+    public SetupClientTask(InternalData data) : base("Setup Client")
     {
-        private InternalData _data;
-
-        public SetupClientTask(InternalData data) : base("Setup Client")
-        {
-            _data = data;
-        }
-
-        public override async Task<IResult> TaskOperation()
-        {
-            var targetInstallDirInfo = new DirectoryInfo(_data.TargetInstallPath);
-
-            var patcherOutputDir = new DirectoryInfo(Path.Join(_data.TargetInstallPath, "patcher"));
-
-            var patcherEXE = new FileInfo(Path.Join(_data.TargetInstallPath, "patcher.exe"));
-
-            var progress = new Progress<double>((d) => { SetStatus(null, null, (int)Math.Floor(d)); });
-
-
-            if (_data.PatchNeeded)
-            {
-                // extract patcher files
-                SetStatus("Extrating Patcher", "", 0);
-
-                var extractPatcherResult = ZipHelper.Decompress(_data.PatcherZipInfo, patcherOutputDir, progress);
-
-                if (!extractPatcherResult.Succeeded)
-                {
-                    return extractPatcherResult;
-                }
-
-                // copy patcher files to install directory
-                SetStatus("Copying Patcher", "", 0);
-
-                var patcherDirInfo = patcherOutputDir.GetDirectories("Patcher*", SearchOption.TopDirectoryOnly).First();
-
-                var copyPatcherResult = FileHelper.CopyDirectoryWithProgress(patcherDirInfo, targetInstallDirInfo, progress);
-
-                if (!copyPatcherResult.Succeeded)
-                {
-                    return copyPatcherResult;
-                }
-
-                // run patcher
-                SetStatus("Running Patcher", "", null, ProgressStyle.Indeterminate);
-
-                var patchingResult = ProcessHelper.PatchClientFiles(patcherEXE, targetInstallDirInfo);
-
-                if (!patchingResult.Succeeded)
-                {
-                    return patchingResult;
-                }
-            }
-
-            // extract release files
-            SetStatus("Extracting Release", "", 0);
-
-            var extractReleaseResult = ZipHelper.Decompress(_data.AkiZipInfo, targetInstallDirInfo, progress);
-
-            if (!extractReleaseResult.Succeeded)
-            {
-                return extractReleaseResult;
-            }
-
-            // cleanup temp files
-            SetStatus("Cleanup", "almost done :)", null, ProgressStyle.Indeterminate);
-
-            if(_data.PatchNeeded)
-            {
-                patcherOutputDir.Delete(true);
-                patcherEXE.Delete();
-            }
-
-            return Result.FromSuccess("SPT is Setup. Happy Playing!");
-        }
+        _data = data;
     }
-}
+
+    public override async Task<IResult> TaskOperation()
+    {
+        var targetInstallDirInfo = new DirectoryInfo(_data.TargetInstallPath);
+
+        var patcherOutputDir = new DirectoryInfo(Path.Join(_data.TargetInstallPath, "patcher"));
+
+        var patcherEXE = new FileInfo(Path.Join(_data.TargetInstallPath, "patcher.exe"));
+
+        var progress = new Progress<double>((d) => { SetStatus(null, null, (int)Math.Floor(d)); });
+
+
+        if (_data.PatchNeeded)
+        {
+            // extract patcher files
+            SetStatus("Extrating Patcher", "", 0);
+
+            var extractPatcherResult = ZipHelper.Decompress(_data.PatcherZipInfo, patcherOutputDir, progress);
+
+            if (!extractPatcherResult.Succeeded)
+            {
+                return extractPatcherResult;
+            }
+
+            // copy patcher files to install directory
+            SetStatus("Copying Patcher", "", 0);
+
+            var patcherDirInfo = patcherOutputDir.GetDirectories("Patcher*", SearchOption.TopDirectoryOnly).First();
+
+            var copyPatcherResult = FileHelper.CopyDirectoryWithProgress(patcherDirInfo, targetInstallDirInfo, progress);
+
+            if (!copyPatcherResult.Succeeded)
+            {
+                return copyPatcherResult;
+            }
+
+            // run patcher
+            SetStatus("Running Patcher", "", null, ProgressStyle.Indeterminate);
+
+            var patchingResult = ProcessHelper.PatchClientFiles(patcherEXE, targetInstallDirInfo);
+
+            if (!patchingResult.Succeeded)
+            {
+                return patchingResult;
+            }
+        }
+
+        // extract release files
+        SetStatus("Extracting Release", "", 0);
+
+        var extractReleaseResult = ZipHelper.Decompress(_data.AkiZipInfo, targetInstallDirInfo, progress);
+
+        if (!extractReleaseResult.Succeeded)
+        {
+            return extractReleaseResult;
+        }
+
+        // cleanup temp files
+        SetStatus("Cleanup", "almost done :)", null, ProgressStyle.Indeterminate);
+
+        if(_data.PatchNeeded)
+        {
+            patcherOutputDir.Delete(true);
+            patcherEXE.Delete();
+        }
+
+        return Result.FromSuccess("SPT is Setup. Happy Playing!");
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Installer Tasks/TestTask.cs b/SPTInstaller/Installer Tasks/TestTask.cs
index 2ce0d1a..537ef50 100644
--- a/SPTInstaller/Installer Tasks/TestTask.cs	
+++ b/SPTInstaller/Installer Tasks/TestTask.cs	
@@ -1,35 +1,33 @@
 using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
-using System;
 using System.Threading.Tasks;
 
-namespace SPTInstaller.Installer_Tasks
+namespace SPTInstaller.Installer_Tasks;
+
+internal class TestTask : InstallerTaskBase
 {
-    internal class TestTask : InstallerTaskBase
+    public static TestTask FromRandomName() => new TestTask($"Test Task #{new Random().Next(0, 9999)}");
+
+    public TestTask(string name) : base(name)
     {
-        public static TestTask FromRandomName() => new TestTask($"Test Task #{new Random().Next(0, 9999)}");
-
-        public TestTask(string name) : base(name)
-        {
-        }
-
-        public async override Task<IResult> TaskOperation()
-        {
-            int total = 4;
-            TimeSpan interval = TimeSpan.FromSeconds(1);
-
-            for(int i = 0; i < total; i++)
-            {
-                var count = i + 1;
-                string progressMessage = $"Running Task: {Name}";
-                int progress = (int)Math.Floor((double)count / total * 100);
-
-                SetStatus(progressMessage, $"Details: ({count}/{total})", progress);
-
-                await Task.Delay(interval);
-            }
-
-            return Result.FromSuccess();
-        }
     }
-}
+
+    public async override Task<IResult> TaskOperation()
+    {
+        var total = 4;
+        var interval = TimeSpan.FromSeconds(1);
+
+        for(var i = 0; i < total; i++)
+        {
+            var count = i + 1;
+            var progressMessage = $"Running Task: {Name}";
+            var progress = (int)Math.Floor((double)count / total * 100);
+
+            SetStatus(progressMessage, $"Details: ({count}/{total})", progress);
+
+            await Task.Delay(interval);
+        }
+
+        return Result.FromSuccess();
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Interfaces/IPreCheck.cs b/SPTInstaller/Interfaces/IPreCheck.cs
index 0618875..34f20cc 100644
--- a/SPTInstaller/Interfaces/IPreCheck.cs
+++ b/SPTInstaller/Interfaces/IPreCheck.cs
@@ -1,17 +1,16 @@
 using System.Threading.Tasks;
 
-namespace SPTInstaller.Interfaces
+namespace SPTInstaller.Interfaces;
+
+public interface IPreCheck
 {
-    public interface IPreCheck
-    {
-        public string Id { get; }
-        public string Name { get; }
-        public bool IsRequired { get; }
+    public string Id { get; }
+    public string Name { get; }
+    public bool IsRequired { get; }
 
-        public bool IsPending { get; set; }
+    public bool IsPending { get; set; }
         
-        public bool Passed { get; }
+    public bool Passed { get; }
 
-        public Task<IResult> RunCheck();
-    }
-}
+    public Task<IResult> RunCheck();
+}
\ No newline at end of file
diff --git a/SPTInstaller/Interfaces/IProgressableTask.cs b/SPTInstaller/Interfaces/IProgressableTask.cs
index 3eb58b2..5d343bf 100644
--- a/SPTInstaller/Interfaces/IProgressableTask.cs
+++ b/SPTInstaller/Interfaces/IProgressableTask.cs
@@ -1,24 +1,23 @@
 using System.Threading.Tasks;
 
-namespace SPTInstaller.Interfaces
+namespace SPTInstaller.Interfaces;
+
+public interface IProgressableTask
 {
-    public interface IProgressableTask
-    {
-        public string Id { get; }
-        public string Name { get; }
+    public string Id { get; }
+    public string Name { get; }
 
-        public bool IsCompleted { get; }
+    public bool IsCompleted { get; }
 
-        public bool HasErrors { get; }
+    public bool HasErrors { get; }
 
-        public bool IsRunning { get; }
+    public bool IsRunning { get; }
 
-        public string StatusMessage { get; }
+    public string StatusMessage { get; }
 
-        public int Progress { get; }
+    public int Progress { get; }
 
-        public bool ShowProgress { get; }
+    public bool ShowProgress { get; }
 
-        public Task<IResult> RunAsync();
-    }
-}
+    public Task<IResult> RunAsync();
+}
\ No newline at end of file
diff --git a/SPTInstaller/Interfaces/IResult.cs b/SPTInstaller/Interfaces/IResult.cs
index 43d9a75..46bf9c5 100644
--- a/SPTInstaller/Interfaces/IResult.cs
+++ b/SPTInstaller/Interfaces/IResult.cs
@@ -1,14 +1,7 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+namespace SPTInstaller.Interfaces;
 
-namespace SPTInstaller.Interfaces
+public interface IResult
 {
-    public interface IResult
-    {
-        public bool Succeeded { get; }
-        public string Message { get; }
-    }
-}
+    public bool Succeeded { get; }
+    public string Message { get; }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Models/DownloadMirror.cs b/SPTInstaller/Models/DownloadMirror.cs
index c3dbc2c..40a83fd 100644
--- a/SPTInstaller/Models/DownloadMirror.cs
+++ b/SPTInstaller/Models/DownloadMirror.cs
@@ -1,8 +1,7 @@
-namespace SPTInstaller.Models
+namespace SPTInstaller.Models;
+
+public class DownloadMirror
 {
-    public class DownloadMirror
-    {
-        public string Link { get; set; }
-        public string Hash { get; set; }
-    }
-}
+    public string Link { get; set; }
+    public string Hash { get; set; }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Models/InstallerTaskBase.cs b/SPTInstaller/Models/InstallerTaskBase.cs
index eb939cb..bafa7f0 100644
--- a/SPTInstaller/Models/InstallerTaskBase.cs
+++ b/SPTInstaller/Models/InstallerTaskBase.cs
@@ -1,183 +1,178 @@
-using Avalonia.Threading;
-using ReactiveUI;
+using ReactiveUI;
 using Serilog;
-using Splat;
 using SPTInstaller.Interfaces;
-using System;
-using System.Security;
 using System.Threading.Tasks;
 
-namespace SPTInstaller.Models
+namespace SPTInstaller.Models;
+
+public abstract class InstallerTaskBase : ReactiveObject, IProgressableTask
 {
-    public abstract class InstallerTaskBase : ReactiveObject, IProgressableTask
+    private string _id;
+    public string Id
     {
-        private string _id;
-        public string Id
-        {
-            get => _id;
-            private set => this.RaiseAndSetIfChanged(ref _id, value);
-        }
+        get => _id;
+        private set => this.RaiseAndSetIfChanged(ref _id, value);
+    }
 
-        private string _name;
-        public string Name
-        {
-            get => _name;
-            private set => this.RaiseAndSetIfChanged(ref _name, value);
-        }
+    private string _name;
+    public string Name
+    {
+        get => _name;
+        private set => this.RaiseAndSetIfChanged(ref _name, value);
+    }
 
-        private bool _isComleted;
-        public bool IsCompleted
-        {
-            get => _isComleted;
-            private set => this.RaiseAndSetIfChanged(ref _isComleted, value);
-        }
+    private bool _isComleted;
+    public bool IsCompleted
+    {
+        get => _isComleted;
+        private set => this.RaiseAndSetIfChanged(ref _isComleted, value);
+    }
 
-        private bool _hasErrors;
-        public bool HasErrors
-        {
-            get => _hasErrors;
-            private set => this.RaiseAndSetIfChanged(ref _hasErrors, value);
-        }
+    private bool _hasErrors;
+    public bool HasErrors
+    {
+        get => _hasErrors;
+        private set => this.RaiseAndSetIfChanged(ref _hasErrors, value);
+    }
 
-        private bool _isRunning;
-        public bool IsRunning
-        {
-            get => _isRunning;
-            private set => this.RaiseAndSetIfChanged(ref _isRunning, value);
-        }
+    private bool _isRunning;
+    public bool IsRunning
+    {
+        get => _isRunning;
+        private set => this.RaiseAndSetIfChanged(ref _isRunning, value);
+    }
 
-        private int _progress;
-        public int Progress
-        {
-            get => _progress;
-            private set => this.RaiseAndSetIfChanged(ref _progress, value);
-        }
+    private int _progress;
+    public int Progress
+    {
+        get => _progress;
+        private set => this.RaiseAndSetIfChanged(ref _progress, value);
+    }
 
-        private bool _showProgress;
-        public bool ShowProgress
-        {
-            get => _showProgress;
-            private set => this.RaiseAndSetIfChanged(ref _showProgress, value);
-        }
+    private bool _showProgress;
+    public bool ShowProgress
+    {
+        get => _showProgress;
+        private set => this.RaiseAndSetIfChanged(ref _showProgress, value);
+    }
 
-        private bool _indeterminateProgress;
-        public bool IndeterminateProgress
-        {
-            get => _indeterminateProgress;
-            private set => this.RaiseAndSetIfChanged(ref _indeterminateProgress, value);
-        }
+    private bool _indeterminateProgress;
+    public bool IndeterminateProgress
+    {
+        get => _indeterminateProgress;
+        private set => this.RaiseAndSetIfChanged(ref _indeterminateProgress, value);
+    }
 
-        private string _statusMessage;
-        public string StatusMessage
-        {
-            get => _statusMessage;
-            private set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
-        }
+    private string _statusMessage;
+    public string StatusMessage
+    {
+        get => _statusMessage;
+        private set => this.RaiseAndSetIfChanged(ref _statusMessage, value);
+    }
 
-        private string _statusDetails;
-        public string StatusDetails
-        {
-            get => _statusDetails;
-            private set => this.RaiseAndSetIfChanged(ref _statusDetails, value);
-        }
+    private string _statusDetails;
+    public string StatusDetails
+    {
+        get => _statusDetails;
+        private set => this.RaiseAndSetIfChanged(ref _statusDetails, value);
+    }
 
-        public enum ProgressStyle
-        {
-            Hidden = 0,
-            Shown,
-            Indeterminate,
-        }
+    public enum ProgressStyle
+    {
+        Hidden = 0,
+        Shown,
+        Indeterminate,
+    }
 
-        /// <summary>
-        /// Update the status details of the task
-        /// </summary>
-        /// <param name="message">The main message to display. Not updated if null</param>
-        /// <param name="details">The details of the task. Not updated if null</param>
-        /// <param name="progress">Progress of the task. Overrides progressStyle if a non-null value is supplied</param>
-        /// <param name="progressStyle">The style of the progress bar</param>
-        public void SetStatus(string? message, string? details, int? progress = null, ProgressStyle? progressStyle = null, bool noLog = false)
+    /// <summary>
+    /// Update the status details of the task
+    /// </summary>
+    /// <param name="message">The main message to display. Not updated if null</param>
+    /// <param name="details">The details of the task. Not updated if null</param>
+    /// <param name="progress">Progress of the task. Overrides progressStyle if a non-null value is supplied</param>
+    /// <param name="progressStyle">The style of the progress bar</param>
+    public void SetStatus(string? message, string? details, int? progress = null, ProgressStyle? progressStyle = null, bool noLog = false)
+    {
+        if(message != null && message != StatusMessage)
         {
-            if(message != null && message != StatusMessage)
+            if (!noLog && !string.IsNullOrWhiteSpace(message))
             {
-                if (!noLog && !string.IsNullOrWhiteSpace(message))
-                {
-                    Log.Information($" <===> {message} <===>");
-                }
-
-                StatusMessage = message;
+                Log.Information($" <===> {message} <===>");
             }
 
-            if(details != null && details != StatusDetails)
-            {
-                if (!noLog && !string.IsNullOrWhiteSpace(details))
-                {
-                    Log.Information(details);
-                }
+            StatusMessage = message;
+        }
 
-                StatusDetails = details;
+        if(details != null && details != StatusDetails)
+        {
+            if (!noLog && !string.IsNullOrWhiteSpace(details))
+            {
+                Log.Information(details);
             }
 
-            if (progressStyle != null)
-            {
-                switch (progressStyle)
-                {
-                    case ProgressStyle.Hidden:
-                        ShowProgress = false;
-                        IndeterminateProgress = false;
-                        break;
-                    case ProgressStyle.Shown:
-                        ShowProgress = true;
-                        IndeterminateProgress = false;
-                        break;
-                    case ProgressStyle.Indeterminate:
-                        ShowProgress = true;
-                        IndeterminateProgress = true;
-                        break;
-                }
-            }
+            StatusDetails = details;
+        }
 
-            if (progress != null)
+        if (progressStyle != null)
+        {
+            switch (progressStyle)
             {
-                ShowProgress = true;
-                IndeterminateProgress = false;
-                Progress = progress.Value;
+                case ProgressStyle.Hidden:
+                    ShowProgress = false;
+                    IndeterminateProgress = false;
+                    break;
+                case ProgressStyle.Shown:
+                    ShowProgress = true;
+                    IndeterminateProgress = false;
+                    break;
+                case ProgressStyle.Indeterminate:
+                    ShowProgress = true;
+                    IndeterminateProgress = true;
+                    break;
             }
         }
 
-        public InstallerTaskBase(string name)
+        if (progress != null)
         {
-            Name = name;
-            Id = Guid.NewGuid().ToString();
+            ShowProgress = true;
+            IndeterminateProgress = false;
+            Progress = progress.Value;
         }
+    }
 
-        /// <summary>
-        /// A method for the install controller to call. Do not use this within your task
-        /// </summary>
-        /// <returns></returns>
-        public async Task<IResult> RunAsync()
+    public InstallerTaskBase(string name)
+    {
+        Name = name;
+        Id = Guid.NewGuid().ToString();
+    }
+
+    /// <summary>
+    /// A method for the install controller to call. Do not use this within your task
+    /// </summary>
+    /// <returns></returns>
+    public async Task<IResult> RunAsync()
+    {
+        IsRunning = true;
+
+        var result = await TaskOperation();
+
+        IsRunning = false;
+
+        if (!result.Succeeded)
         {
-            IsRunning = true;
-
-            var result = await TaskOperation();
-
-            IsRunning = false;
-
-            if (!result.Succeeded)
-            {
-                HasErrors = true;
-
-                return result;
-            }
-
-            IsCompleted = true;
+            HasErrors = true;
 
             return result;
         }
 
-        /// <summary>
-        /// The task you want to run
-        /// </summary>
-        /// <returns></returns>
-        public abstract Task<IResult> TaskOperation();
+        IsCompleted = true;
+
+        return result;
     }
-}
+
+    /// <summary>
+    /// The task you want to run
+    /// </summary>
+    /// <returns></returns>
+    public abstract Task<IResult> TaskOperation();
+}
\ No newline at end of file
diff --git a/SPTInstaller/Models/InternalData.cs b/SPTInstaller/Models/InternalData.cs
index 0c93498..3f9f423 100644
--- a/SPTInstaller/Models/InternalData.cs
+++ b/SPTInstaller/Models/InternalData.cs
@@ -1,58 +1,56 @@
 using System.Collections.Generic;
-using System.IO;
 
-namespace SPTInstaller.Models
+namespace SPTInstaller.Models;
+
+public class InternalData
 {
-    public class InternalData
-    {
-        /// <summary>
-        /// The folder to install SPT into
-        /// </summary>
-        public string? TargetInstallPath { get; set; }
+    /// <summary>
+    /// The folder to install SPT into
+    /// </summary>
+    public string? TargetInstallPath { get; set; }
 
-        /// <summary>
-        /// The orginal EFT game path
-        /// </summary>
-        public string? OriginalGamePath { get; set; }
+    /// <summary>
+    /// The orginal EFT game path
+    /// </summary>
+    public string? OriginalGamePath { get; set; }
 
-        /// <summary>
-        /// The original EFT game version
-        /// </summary>
-        public string OriginalGameVersion { get; set; }
+    /// <summary>
+    /// The original EFT game version
+    /// </summary>
+    public string OriginalGameVersion { get; set; }
 
-        /// <summary>
-        /// Patcher zip file info
-        /// </summary>
-        public FileInfo PatcherZipInfo { get; set; }
+    /// <summary>
+    /// Patcher zip file info
+    /// </summary>
+    public FileInfo PatcherZipInfo { get; set; }
 
-        /// <summary>
-        /// SPT-AKI zip file info
-        /// </summary>
-        public FileInfo AkiZipInfo { get; set; }
+    /// <summary>
+    /// SPT-AKI zip file info
+    /// </summary>
+    public FileInfo AkiZipInfo { get; set; }
 
-        /// <summary>
-        /// The release download link for SPT-AKI
-        /// </summary>
-        public string AkiReleaseDownloadLink { get; set; }
+    /// <summary>
+    /// The release download link for SPT-AKI
+    /// </summary>
+    public string AkiReleaseDownloadLink { get; set; }
 
-        /// <summary>
-        /// The release zip hash
-        /// </summary>
-        public string AkiReleaseHash { get; set; } = null;
+    /// <summary>
+    /// The release zip hash
+    /// </summary>
+    public string AkiReleaseHash { get; set; } = null;
 
-        /// <summary>
-        /// The release download link for the patcher mirror list
-        /// </summary>
-        public string PatcherMirrorsLink { get; set; }
+    /// <summary>
+    /// The release download link for the patcher mirror list
+    /// </summary>
+    public string PatcherMirrorsLink { get; set; }
 
-        /// <summary>
-        /// The release download mirrors for the patcher
-        /// </summary>
-        public List<DownloadMirror> PatcherReleaseMirrors { get; set; } = null;
+    /// <summary>
+    /// The release download mirrors for the patcher
+    /// </summary>
+    public List<DownloadMirror> PatcherReleaseMirrors { get; set; } = null;
 
-        /// <summary>
-        /// Whether or not a patch is needed to downgrade the client files
-        /// </summary>
-        public bool PatchNeeded { get; set; }
-    }
-}
+    /// <summary>
+    /// Whether or not a patch is needed to downgrade the client files
+    /// </summary>
+    public bool PatchNeeded { get; set; }
+}
\ No newline at end of file
diff --git a/SPTInstaller/Models/PreCheckBase.cs b/SPTInstaller/Models/PreCheckBase.cs
index 416986f..923b727 100644
--- a/SPTInstaller/Models/PreCheckBase.cs
+++ b/SPTInstaller/Models/PreCheckBase.cs
@@ -1,76 +1,74 @@
 using ReactiveUI;
 using SPTInstaller.Interfaces;
-using System;
 using System.Threading.Tasks;
 
-namespace SPTInstaller.Models
+namespace SPTInstaller.Models;
+
+public abstract class PreCheckBase : ReactiveObject, IPreCheck
 {
-    public abstract class PreCheckBase : ReactiveObject, IPreCheck
+    private string _id;
+    public string Id
     {
-        private string _id;
-        public string Id
-        {
-            get => _id;
-            set => this.RaiseAndSetIfChanged(ref _id, value);
-        }
-
-        private string _name;
-        public string Name
-        {
-            get => _name;
-            set => this.RaiseAndSetIfChanged(ref _name, value);
-        }
-
-        private bool _required;
-        public bool IsRequired
-        {
-            get => _required;
-            set => this.RaiseAndSetIfChanged(ref _required, value);
-        }
-
-        private bool _passed;
-        public bool Passed
-        {
-            get => _passed;
-            set => this.RaiseAndSetIfChanged(ref _passed, value);
-        }
-
-        private bool _isPending;
-        public bool IsPending
-        {
-            get => _isPending;
-            set => this.RaiseAndSetIfChanged(ref _isPending, value);
-        }
-
-        private bool _isRunning;
-        public bool IsRunning
-        {
-            get => _isRunning;
-            set => this.RaiseAndSetIfChanged(ref _isRunning, value);
-        }
-
-        /// <summary>
-        /// Base class for pre-checks to run before installation
-        /// </summary>
-        /// <param name="name">The display name of the pre-check</param>
-        /// <param name="required">If installation should stop on failing this pre-check</param>
-        public PreCheckBase(string name, bool required)
-        {
-            Name = name;
-            IsRequired = required;
-            Id = Guid.NewGuid().ToString();
-        }
-
-        public async Task<IResult> RunCheck()
-        {
-            IsRunning = true;
-            Passed = await CheckOperation();
-            IsRunning = false;
-            IsPending = false;
-
-            return Passed ? Result.FromSuccess() : Result.FromError($"PreCheck Failed: {Name}");
-        }
-
-        public abstract Task<bool> CheckOperation();
+        get => _id;
+        set => this.RaiseAndSetIfChanged(ref _id, value);
     }
-}
+
+    private string _name;
+    public string Name
+    {
+        get => _name;
+        set => this.RaiseAndSetIfChanged(ref _name, value);
+    }
+
+    private bool _required;
+    public bool IsRequired
+    {
+        get => _required;
+        set => this.RaiseAndSetIfChanged(ref _required, value);
+    }
+
+    private bool _passed;
+    public bool Passed
+    {
+        get => _passed;
+        set => this.RaiseAndSetIfChanged(ref _passed, value);
+    }
+
+    private bool _isPending;
+    public bool IsPending
+    {
+        get => _isPending;
+        set => this.RaiseAndSetIfChanged(ref _isPending, value);
+    }
+
+    private bool _isRunning;
+    public bool IsRunning
+    {
+        get => _isRunning;
+        set => this.RaiseAndSetIfChanged(ref _isRunning, value);
+    }
+
+    /// <summary>
+    /// Base class for pre-checks to run before installation
+    /// </summary>
+    /// <param name="name">The display name of the pre-check</param>
+    /// <param name="required">If installation should stop on failing this pre-check</param>
+    public PreCheckBase(string name, bool required)
+    {
+        Name = name;
+        IsRequired = required;
+        Id = Guid.NewGuid().ToString();
+    }
+
+    public async Task<IResult> RunCheck()
+    {
+        IsRunning = true;
+        Passed = await CheckOperation();
+        IsRunning = false;
+        IsPending = false;
+
+        return Passed ? Result.FromSuccess() : Result.FromError($"PreCheck Failed: {Name}");
+    }
+
+    public abstract Task<bool> CheckOperation();
+}
\ No newline at end of file
diff --git a/SPTInstaller/Models/Result.cs b/SPTInstaller/Models/Result.cs
index bb520d0..d962e5c 100644
--- a/SPTInstaller/Models/Result.cs
+++ b/SPTInstaller/Models/Result.cs
@@ -1,20 +1,19 @@
 using SPTInstaller.Interfaces;
 
-namespace SPTInstaller.Models
+namespace SPTInstaller.Models;
+
+public class Result : IResult
 {
-    public class Result : IResult
+    public bool Succeeded { get; private set; }
+
+    public string Message { get; private set; }
+
+    protected Result(string message, bool succeeded)
     {
-        public bool Succeeded { get; private set; }
-
-        public string Message { get; private set; }
-
-        protected Result(string message, bool succeeded)
-        {
-            Message = message;
-            Succeeded = succeeded;
-        }
-
-        public static Result FromSuccess(string message = "") => new Result(message, true);
-        public static Result FromError(string message) => new Result(message, false);
+        Message = message;
+        Succeeded = succeeded;
     }
-}
+
+    public static Result FromSuccess(string message = "") => new(message, true);
+    public static Result FromError(string message) => new(message, false);
+}
\ No newline at end of file
diff --git a/SPTInstaller/Program.cs b/SPTInstaller/Program.cs
index 78e8dc9..ccc1b17 100644
--- a/SPTInstaller/Program.cs
+++ b/SPTInstaller/Program.cs
@@ -12,44 +12,44 @@ using SPTInstaller.Models;
 using System.Linq;
 using System.Reflection;
 
-namespace SPTInstaller
+namespace SPTInstaller;
+
+internal class Program
 {
-    internal class Program
+    // Initialization code. Don't use any Avalonia, third-party APIs or any
+    // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+    // yet and stuff might break.
+    [STAThread]
+    public static void Main(string[] args) => BuildAvaloniaApp()
+        .StartWithClassicDesktopLifetime(args);
+
+    // Avalonia configuration, don't remove; also used by visual designer.
+    public static AppBuilder BuildAvaloniaApp()
     {
-        // Initialization code. Don't use any Avalonia, third-party APIs or any
-        // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
-        // yet and stuff might break.
-        [STAThread]
-        public static void Main(string[] args) => BuildAvaloniaApp()
-            .StartWithClassicDesktopLifetime(args);
+        Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetExecutingAssembly());
 
-        // Avalonia configuration, don't remove; also used by visual designer.
-        public static AppBuilder BuildAvaloniaApp()
-        {
-            Locator.CurrentMutable.RegisterViewsForViewModels(Assembly.GetExecutingAssembly());
-
-            // Register all the things
-            // Regestering as base classes so ReactiveUI works correctly. Doesn't seem to like the interfaces :(
-            ServiceHelper.Register<InternalData>();
-            ServiceHelper.Register<PreCheckBase, NetFramework472PreCheck>();
-            ServiceHelper.Register<PreCheckBase, NetCore6PreCheck>();
-            ServiceHelper.Register<PreCheckBase, FreeSpacePreCheck>();
+        // Register all the things
+        // Regestering as base classes so ReactiveUI works correctly. Doesn't seem to like the interfaces :(
+        ServiceHelper.Register<InternalData>();
+        ServiceHelper.Register<PreCheckBase, NetFramework472PreCheck>();
+        ServiceHelper.Register<PreCheckBase, NetCore6PreCheck>();
+        ServiceHelper.Register<PreCheckBase, FreeSpacePreCheck>();
 #if !TEST
-            var logPath = Path.Join(Environment.CurrentDirectory, "spt-aki-installer_.log");
+        var logPath = Path.Join(Environment.CurrentDirectory, "spt-aki-installer_.log");
 
-            Log.Logger = new LoggerConfiguration()
-                         .MinimumLevel.Debug()
-                         .WriteTo
-                         .File(path: logPath,
-                               restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Debug, 
-                               rollingInterval: RollingInterval.Day)
-                         .CreateLogger();
+        Log.Logger = new LoggerConfiguration()
+            .MinimumLevel.Debug()
+            .WriteTo
+            .File(path: logPath,
+                restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Debug, 
+                rollingInterval: RollingInterval.Day)
+            .CreateLogger();
 
-            ServiceHelper.Register<InstallerTaskBase, InitializationTask>();
-            ServiceHelper.Register<InstallerTaskBase, ReleaseCheckTask>();
-            ServiceHelper.Register<InstallerTaskBase, DownloadTask>();
-            ServiceHelper.Register<InstallerTaskBase, CopyClientTask>();
-            ServiceHelper.Register<InstallerTaskBase, SetupClientTask>();
+        ServiceHelper.Register<InstallerTaskBase, InitializationTask>();
+        ServiceHelper.Register<InstallerTaskBase, ReleaseCheckTask>();
+        ServiceHelper.Register<InstallerTaskBase, DownloadTask>();
+        ServiceHelper.Register<InstallerTaskBase, CopyClientTask>();
+        ServiceHelper.Register<InstallerTaskBase, SetupClientTask>();
 #else
             for (int i = 0; i < 5; i++)
             {
@@ -57,19 +57,18 @@ namespace SPTInstaller
             }
 #endif
 
-            // need the interfaces for the controller and splat won't resolve them since we need to base classes in avalonia (what a mess), so doing it manually here
-            var tasks = Locator.Current.GetServices<InstallerTaskBase>().ToArray() as IProgressableTask[];
-            var preChecks = Locator.Current.GetServices<PreCheckBase>().ToArray() as IPreCheck[];
+        // need the interfaces for the controller and splat won't resolve them since we need to base classes in avalonia (what a mess), so doing it manually here
+        var tasks = Locator.Current.GetServices<InstallerTaskBase>().ToArray() as IProgressableTask[];
+        var preChecks = Locator.Current.GetServices<PreCheckBase>().ToArray() as IPreCheck[];
 
-            var installer = new InstallController(tasks, preChecks);
+        var installer = new InstallController(tasks, preChecks);
 
-            // manually register install controller
-            Locator.CurrentMutable.RegisterConstant(installer);
+        // manually register install controller
+        Locator.CurrentMutable.RegisterConstant(installer);
 
-            return AppBuilder.Configure<App>()
-                .UsePlatformDetect()
-                .LogToTrace()
-                .UseReactiveUI();
-        }
+        return AppBuilder.Configure<App>()
+            .UsePlatformDetect()
+            .LogToTrace()
+            .UseReactiveUI();
     }
 }
\ No newline at end of file
diff --git a/SPTInstaller/ViewLocator.cs b/SPTInstaller/ViewLocator.cs
index bf62b2d..f33e897 100644
--- a/SPTInstaller/ViewLocator.cs
+++ b/SPTInstaller/ViewLocator.cs
@@ -1,28 +1,26 @@
 using Avalonia.Controls;
 using Avalonia.Controls.Templates;
 using SPTInstaller.ViewModels;
-using System;
 
-namespace SPTInstaller
+namespace SPTInstaller;
+
+public class ViewLocator : IDataTemplate
 {
-    public class ViewLocator : IDataTemplate
+    public IControl Build(object data)
     {
-        public IControl Build(object data)
+        var name = data.GetType().FullName!.Replace("ViewModel", "View");
+        var type = Type.GetType(name);
+
+        if (type != null)
         {
-            var name = data.GetType().FullName!.Replace("ViewModel", "View");
-            var type = Type.GetType(name);
-
-            if (type != null)
-            {
-                return (Control)Activator.CreateInstance(type)!;
-            }
-
-            return new TextBlock { Text = "Not Found: " + name };
+            return (Control)Activator.CreateInstance(type)!;
         }
 
-        public bool Match(object data)
-        {
-            return data is ViewModelBase;
-        }
+        return new TextBlock { Text = "Not Found: " + name };
+    }
+
+    public bool Match(object data)
+    {
+        return data is ViewModelBase;
     }
 }
\ No newline at end of file
diff --git a/SPTInstaller/ViewModels/InstallViewModel.cs b/SPTInstaller/ViewModels/InstallViewModel.cs
index 80d0870..032e6bb 100644
--- a/SPTInstaller/ViewModels/InstallViewModel.cs
+++ b/SPTInstaller/ViewModels/InstallViewModel.cs
@@ -4,35 +4,32 @@ using SPTInstaller.Helpers;
 using SPTInstaller.Interfaces;
 using SPTInstaller.Models;
 using System.Collections.ObjectModel;
-using System.Linq;
 using System.Threading.Tasks;
 
-namespace SPTInstaller.ViewModels
+namespace SPTInstaller.ViewModels;
+
+public class InstallViewModel : ViewModelBase
 {
-    public class InstallViewModel : ViewModelBase
+    private IProgressableTask _currentTask;
+    public IProgressableTask CurrentTask
     {
-        private IProgressableTask _currentTask;
-        public IProgressableTask CurrentTask
-        {
-            get => _currentTask;
-            set => this.RaiseAndSetIfChanged(ref _currentTask, value);
-        }
-
-        public ObservableCollection<InstallerTaskBase> MyTasks { get; set; } 
-            = new ObservableCollection<InstallerTaskBase>(ServiceHelper.GetAll<InstallerTaskBase>());
-
-        public InstallViewModel(IScreen host) : base(host)
-        {
-            var installer = ServiceHelper.Get<InstallController>();
-
-            installer.TaskChanged += (sender, task) => CurrentTask = task;
-
-            Task.Run(async () => 
-            {
-                var result = await installer.RunTasks();
-
-                NavigateTo(new MessageViewModel(HostScreen, result));
-            });
-        }
+        get => _currentTask;
+        set => this.RaiseAndSetIfChanged(ref _currentTask, value);
     }
-}
+
+    public ObservableCollection<InstallerTaskBase> MyTasks { get; set; } = new(ServiceHelper.GetAll<InstallerTaskBase>());
+
+    public InstallViewModel(IScreen host) : base(host)
+    {
+        var installer = ServiceHelper.Get<InstallController>();
+
+        installer.TaskChanged += (sender, task) => CurrentTask = task;
+
+        Task.Run(async () => 
+        {
+            var result = await installer.RunTasks();
+
+            NavigateTo(new MessageViewModel(HostScreen, result));
+        });
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/ViewModels/MainWindowViewModel.cs b/SPTInstaller/ViewModels/MainWindowViewModel.cs
index 793a76c..8b86439 100644
--- a/SPTInstaller/ViewModels/MainWindowViewModel.cs
+++ b/SPTInstaller/ViewModels/MainWindowViewModel.cs
@@ -1,50 +1,48 @@
 using Avalonia;
 using ReactiveUI;
 using Serilog;
-using System;
 using System.Reflection;
 
-namespace SPTInstaller.ViewModels
+namespace SPTInstaller.ViewModels;
+
+public class MainWindowViewModel : ReactiveObject, IActivatableViewModel, IScreen
 {
-    public class MainWindowViewModel : ReactiveObject, IActivatableViewModel, IScreen
+    public RoutingState Router { get; } = new();
+    public ViewModelActivator Activator { get; } = new();
+
+    private string _title;
+    public string Title
     {
-        public RoutingState Router { get; } = new RoutingState();
-        public ViewModelActivator Activator { get; } = new ViewModelActivator();
-
-        private string _title;
-        public string Title
-        {
-            get => _title;
-            set => this.RaiseAndSetIfChanged(ref _title, value);
-        }
-
-        public MainWindowViewModel()
-        {
-            string? version = Assembly.GetExecutingAssembly().GetName()?.Version?.ToString();
-
-            Title = $"SPT Installer {"v" + version ?? "--unknown version--"}";
-
-            Log.Information($"========= {Title} Started =========");
-            Log.Information(Environment.OSVersion.VersionString);
-
-            Router.Navigate.Execute(new PreChecksViewModel(this));
-        }
-
-        public void CloseCommand()
-        {
-            if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp)
-            {
-                desktopApp.MainWindow.Close();
-            }
-        }
-
-        public void MinimizeCommand()
-        {
-            if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp)
-            {
-                desktopApp.MainWindow.WindowState = Avalonia.Controls.WindowState.Minimized;
-            }
-        }
-
+        get => _title;
+        set => this.RaiseAndSetIfChanged(ref _title, value);
     }
+
+    public MainWindowViewModel()
+    {
+        string? version = Assembly.GetExecutingAssembly().GetName()?.Version?.ToString();
+
+        Title = $"SPT Installer {"v" + version ?? "--unknown version--"}";
+
+        Log.Information($"========= {Title} Started =========");
+        Log.Information(Environment.OSVersion.VersionString);
+
+        Router.Navigate.Execute(new PreChecksViewModel(this));
+    }
+
+    public void CloseCommand()
+    {
+        if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp)
+        {
+            desktopApp.MainWindow.Close();
+        }
+    }
+
+    public void MinimizeCommand()
+    {
+        if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp)
+        {
+            desktopApp.MainWindow.WindowState = Avalonia.Controls.WindowState.Minimized;
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/SPTInstaller/ViewModels/MessageViewModel.cs b/SPTInstaller/ViewModels/MessageViewModel.cs
index 7591382..ab8c097 100644
--- a/SPTInstaller/ViewModels/MessageViewModel.cs
+++ b/SPTInstaller/ViewModels/MessageViewModel.cs
@@ -4,44 +4,43 @@ using Serilog;
 using SPTInstaller.Interfaces;
 using System.Windows.Input;
 
-namespace SPTInstaller.ViewModels
+namespace SPTInstaller.ViewModels;
+
+public class MessageViewModel : ViewModelBase
 {
-    public class MessageViewModel : ViewModelBase
+    private bool _HasErrors;
+    public bool HasErrors
     {
-        private bool _HasErrors;
-        public bool HasErrors
-        {
-            get => _HasErrors;
-            set => this.RaiseAndSetIfChanged(ref _HasErrors, value);
-        }
-
-        private string _Message;
-        public string Message
-        {
-            get => _Message;
-            set => this.RaiseAndSetIfChanged(ref _Message, value);
-        }
-
-        public ICommand CloseCommand { get; set; } = ReactiveCommand.Create(() =>
-        {
-            if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp)
-            {
-                desktopApp.MainWindow.Close();
-            }
-        });
-
-        public MessageViewModel(IScreen Host, IResult result) : base(Host)
-        {
-            Message = result.Message;
-
-            if(result.Succeeded)
-            {
-                Log.Information(Message);
-                return;
-            }
-
-            HasErrors = true;
-            Log.Error(Message);
-        }
+        get => _HasErrors;
+        set => this.RaiseAndSetIfChanged(ref _HasErrors, value);
     }
-}
+
+    private string _Message;
+    public string Message
+    {
+        get => _Message;
+        set => this.RaiseAndSetIfChanged(ref _Message, value);
+    }
+
+    public ICommand CloseCommand { get; set; } = ReactiveCommand.Create(() =>
+    {
+        if (Application.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktopApp)
+        {
+            desktopApp.MainWindow.Close();
+        }
+    });
+
+    public MessageViewModel(IScreen Host, IResult result) : base(Host)
+    {
+        Message = result.Message;
+
+        if(result.Succeeded)
+        {
+            Log.Information(Message);
+            return;
+        }
+
+        HasErrors = true;
+        Log.Error(Message);
+    }
+}
\ No newline at end of file
diff --git a/SPTInstaller/ViewModels/ViewModelBase.cs b/SPTInstaller/ViewModels/ViewModelBase.cs
index 8d85c91..32728a7 100644
--- a/SPTInstaller/ViewModels/ViewModelBase.cs
+++ b/SPTInstaller/ViewModels/ViewModelBase.cs
@@ -1,61 +1,58 @@
 using Avalonia.Threading;
 using ReactiveUI;
 using System.Threading.Tasks;
-using System;
 
-namespace SPTInstaller.ViewModels
+namespace SPTInstaller.ViewModels;
+
+public class ViewModelBase : ReactiveObject, IActivatableViewModel, IRoutableViewModel
 {
-    public class ViewModelBase : ReactiveObject, IActivatableViewModel, IRoutableViewModel
+    public ViewModelActivator Activator { get; } = new();
+
+    public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 7);
+
+    public IScreen HostScreen { get; }
+
+    /// <summary>
+    /// Delay the return of the viewmodel
+    /// </summary>
+    /// <param name="Milliseconds">The amount of time in milliseconds to delay</param>
+    /// <returns>The viewmodel after the delay time</returns>
+    /// <remarks>Useful to delay the navigation to another view. For instance, to allow an animation to complete.</remarks>
+    private async Task<ViewModelBase> WithDelay(int Milliseconds)
     {
-        public ViewModelActivator Activator { get; } = new ViewModelActivator();
+        await Task.Delay(Milliseconds);
 
-        public string? UrlPathSegment => Guid.NewGuid().ToString().Substring(0, 7);
-
-        public IScreen HostScreen { get; }
-
-        /// <summary>
-        /// Delay the return of the viewmodel
-        /// </summary>
-        /// <param name="Milliseconds">The amount of time in milliseconds to delay</param>
-        /// <returns>The viewmodel after the delay time</returns>
-        /// <remarks>Useful to delay the navigation to another view. For instance, to allow an animation to complete.</remarks>
-        private async Task<ViewModelBase> WithDelay(int Milliseconds)
-        {
-            await Task.Delay(Milliseconds);
-
-            return this;
-        }
-
-        /// <summary>
-        /// Navigate to another viewmodel after a delay
-        /// </summary>
-        /// <param name="ViewModel"></param>
-        /// <param name="Milliseconds"></param>
-        /// <returns></returns>
-        public async Task NavigateToWithDelay(ViewModelBase ViewModel, int Milliseconds)
-        {
-            await Dispatcher.UIThread.InvokeAsync(async () =>
-            {
-                HostScreen.Router.Navigate.Execute(await ViewModel.WithDelay(Milliseconds));
-            });
-        }
-
-        /// <summary>
-        /// Navigate to another viewmodel
-        /// </summary>
-        /// <param name="ViewModel"></param>
-        public void NavigateTo(ViewModelBase ViewModel)
-        {
-            Dispatcher.UIThread.InvokeAsync(() =>
-            {
-                HostScreen.Router.Navigate.Execute(ViewModel);
-            });
-        }
-
-        public ViewModelBase(IScreen Host)
-        {
-            HostScreen = Host;
-        }
+        return this;
     }
 
+    /// <summary>
+    /// Navigate to another viewmodel after a delay
+    /// </summary>
+    /// <param name="ViewModel"></param>
+    /// <param name="Milliseconds"></param>
+    /// <returns></returns>
+    public async Task NavigateToWithDelay(ViewModelBase ViewModel, int Milliseconds)
+    {
+        await Dispatcher.UIThread.InvokeAsync(async () =>
+        {
+            HostScreen.Router.Navigate.Execute(await ViewModel.WithDelay(Milliseconds));
+        });
+    }
+
+    /// <summary>
+    /// Navigate to another viewmodel
+    /// </summary>
+    /// <param name="ViewModel"></param>
+    public void NavigateTo(ViewModelBase ViewModel)
+    {
+        Dispatcher.UIThread.InvokeAsync(() =>
+        {
+            HostScreen.Router.Navigate.Execute(ViewModel);
+        });
+    }
+
+    public ViewModelBase(IScreen Host)
+    {
+        HostScreen = Host;
+    }
 }
\ No newline at end of file
diff --git a/SPTInstaller/Views/InstallView.axaml.cs b/SPTInstaller/Views/InstallView.axaml.cs
index 813f5f0..1b8a5b7 100644
--- a/SPTInstaller/Views/InstallView.axaml.cs
+++ b/SPTInstaller/Views/InstallView.axaml.cs
@@ -1,14 +1,12 @@
-using Avalonia.Controls;
 using Avalonia.ReactiveUI;
 using SPTInstaller.ViewModels;
 
-namespace SPTInstaller.Views
+namespace SPTInstaller.Views;
+
+public partial class InstallView : ReactiveUserControl<InstallViewModel>
 {
-    public partial class InstallView : ReactiveUserControl<InstallViewModel>
+    public InstallView()
     {
-        public InstallView()
-        {
-            InitializeComponent();
-        }
+        InitializeComponent();
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/Views/MainWindow.axaml.cs b/SPTInstaller/Views/MainWindow.axaml.cs
index edc3580..1e69f06 100644
--- a/SPTInstaller/Views/MainWindow.axaml.cs
+++ b/SPTInstaller/Views/MainWindow.axaml.cs
@@ -1,12 +1,11 @@
 using Avalonia.Controls;
 
-namespace SPTInstaller.Views
+namespace SPTInstaller.Views;
+
+public partial class MainWindow : Window
 {
-    public partial class MainWindow : Window
+    public MainWindow()
     {
-        public MainWindow()
-        {
-            InitializeComponent();
-        }
+        InitializeComponent();
     }
 }
\ No newline at end of file
diff --git a/SPTInstaller/Views/MessageView.axaml.cs b/SPTInstaller/Views/MessageView.axaml.cs
index 9d37338..c89811d 100644
--- a/SPTInstaller/Views/MessageView.axaml.cs
+++ b/SPTInstaller/Views/MessageView.axaml.cs
@@ -1,14 +1,12 @@
-using Avalonia.Controls;
 using Avalonia.ReactiveUI;
 using SPTInstaller.ViewModels;
 
-namespace SPTInstaller.Views
+namespace SPTInstaller.Views;
+
+public partial class MessageView : ReactiveUserControl<MessageViewModel>
 {
-    public partial class MessageView : ReactiveUserControl<MessageViewModel>
+    public MessageView()
     {
-        public MessageView()
-        {
-            InitializeComponent();
-        }
+        InitializeComponent();
     }
-}
+}
\ No newline at end of file
diff --git a/SPTInstaller/Views/PreChecksView.axaml.cs b/SPTInstaller/Views/PreChecksView.axaml.cs
index db0142e..ffc4b0b 100644
--- a/SPTInstaller/Views/PreChecksView.axaml.cs
+++ b/SPTInstaller/Views/PreChecksView.axaml.cs
@@ -1,13 +1,12 @@
 using Avalonia.ReactiveUI;
 using SPTInstaller.ViewModels;
 
-namespace SPTInstaller.Views
+namespace SPTInstaller.Views;
+
+public partial class PreChecksView : ReactiveUserControl<PreChecksViewModel>
 {
-    public partial class PreChecksView : ReactiveUserControl<PreChecksViewModel>
+    public PreChecksView()
     {
-        public PreChecksView()
-        {
-            InitializeComponent();
-        }
+        InitializeComponent();
     }
-}
+}
\ No newline at end of file