diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs index 6635c2415..91b82acbb 100644 --- a/Artemis/Artemis/ArtemisBootstrapper.cs +++ b/Artemis/Artemis/ArtemisBootstrapper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Input; @@ -24,6 +25,9 @@ namespace Artemis public ArtemisBootstrapper() { + // Make sure the data folder exists + GeneralHelpers.SetupDataFolder(); + // Start logging before anything else Logging.SetupLogging(SettingsProvider.Load().LogLevel); // Restore DDLs before interacting with any SDKs diff --git a/Artemis/Artemis/DAL/ProfileProvider.cs b/Artemis/Artemis/DAL/ProfileProvider.cs index 4b0e28181..476482dba 100644 --- a/Artemis/Artemis/DAL/ProfileProvider.cs +++ b/Artemis/Artemis/DAL/ProfileProvider.cs @@ -19,10 +19,8 @@ namespace Artemis.DAL { public static class ProfileProvider { + public static readonly string ProfileFolder = GeneralHelpers.DataFolder + "profiles\\"; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - public static readonly string ProfileFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\profiles"; - private static bool _installedDefaults; static ProfileProvider() @@ -32,7 +30,7 @@ namespace Artemis.DAL CheckProfiles(); InstallDefaults(); } - + public static List GetProfileNames(KeyboardProvider keyboard, ModuleModel module) { if (keyboard == null || module == null) @@ -69,7 +67,7 @@ namespace Artemis.DAL if (!(prof.GameName?.Length > 1) || !(prof.KeyboardSlug?.Length > 1) || !(prof.Slug?.Length > 1)) throw new ArgumentException("Profile is invalid. Name, GameName and KeyboardSlug are required"); - var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}"; + var path = ProfileFolder + $"{prof.KeyboardSlug}\\{prof.GameName}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); @@ -87,7 +85,7 @@ namespace Artemis.DAL return; } - File.WriteAllText(path + $@"\{prof.Slug}.json", json); + File.WriteAllText(path + $"\\{prof.Slug}.json", json); Logger.Debug("Saved profile {0}/{1}/{2}", prof.KeyboardSlug, prof.GameName, prof.Name); } } @@ -103,7 +101,7 @@ namespace Artemis.DAL return; // Store the profile path before it is renamed - var oldPath = ProfileFolder + $@"\{profile.KeyboardSlug}\{profile.GameName}\{profile.Slug}.json"; + var oldPath = ProfileFolder + $"{profile.KeyboardSlug}\\{profile.GameName}\\{profile.Slug}.json"; // Update the profile, creating a new file profile.Name = name; @@ -117,7 +115,7 @@ namespace Artemis.DAL public static void DeleteProfile(ProfileModel prof) { // Remove the file - var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}\{prof.Slug}.json"; + var path = ProfileFolder + $"{prof.KeyboardSlug}\\{prof.GameName}\\{prof.Slug}.json"; if (File.Exists(path)) File.Delete(path); } @@ -145,7 +143,7 @@ namespace Artemis.DAL } /// - /// Exports the given profile to the provided path in JSON + /// Exports the given profile to the provided path in JSON /// /// The profile to export /// The path to save the profile to @@ -155,16 +153,15 @@ namespace Artemis.DAL File.WriteAllText(path, json); } - public static void InsertGif(string effectName, string profileName, string layerName, Bitmap gifFile, - string fileName) + public static void InsertGif(string moduleName, string profileName, string layerName, Bitmap gifFile, string fileName) { var directories = new DirectoryInfo(ProfileFolder).GetDirectories(); var profiles = new List(); foreach (var directoryInfo in directories) - profiles.AddRange(ReadProfiles(directoryInfo.Name + "/effectName").Where(d => d.Name == profileName)); + profiles.AddRange(ReadProfiles(directoryInfo.Name + "\\" + moduleName).Where(d => d.Name == profileName)); // Extract the GIF file - var gifDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\gifs"; + var gifDir = GeneralHelpers.DataFolder + "gifs"; Directory.CreateDirectory(gifDir); var gifPath = gifDir + $"\\{fileName}.gif"; if (!File.Exists(gifPath)) @@ -184,7 +181,7 @@ namespace Artemis.DAL public static List ReadProfiles(string subDirectory) { var profiles = new List(); - var directory = ProfileFolder + "/" + subDirectory; + var directory = ProfileFolder + subDirectory; if (!Directory.Exists(directory)) return profiles; @@ -193,7 +190,6 @@ namespace Artemis.DAL // Parse the JSON files into objects and add them if they are valid foreach (var path in profilePaths) - { try { var prof = LoadProfileIfValid(path); @@ -201,21 +197,15 @@ namespace Artemis.DAL continue; // Only add unique profiles - if (profiles.Any(p => p.GameName == prof.GameName && p.Name == prof.Name && - p.KeyboardSlug == prof.KeyboardSlug)) - { + if (profiles.Any(p => p.GameName == prof.GameName && p.Name == prof.Name && p.KeyboardSlug == prof.KeyboardSlug)) Logger.Info("Didn't load duplicate profile: {0}", path); - } else - { profiles.Add(prof); - } } catch (Exception e) { Logger.Error("Failed to load profile: {0} - {1}", path, e); } - } return profiles; } @@ -232,8 +222,7 @@ namespace Artemis.DAL _installedDefaults = true; // Load the ZIP from resources - var stream = Assembly.GetExecutingAssembly() - .GetManifestResourceStream("Artemis.Resources.Keyboards.default-profiles.zip"); + var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Artemis.Resources.Keyboards.default-profiles.zip"); // Extract it over the old defaults in case one was updated if (stream == null) @@ -241,7 +230,6 @@ namespace Artemis.DAL var archive = new ZipArchive(stream); archive.ExtractToDirectory(ProfileFolder, true); - InsertGif("GeneralProfile", "Demo (duplicate to keep changes)", "GIF", Resources.demo_gif, "demo-gif"); } catch (IOException e) diff --git a/Artemis/Artemis/DAL/SettingsProvider.cs b/Artemis/Artemis/DAL/SettingsProvider.cs index 0e4ecfed6..b3efe2b19 100644 --- a/Artemis/Artemis/DAL/SettingsProvider.cs +++ b/Artemis/Artemis/DAL/SettingsProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Artemis.Settings; +using Artemis.Utilities; using Newtonsoft.Json; using NLog; @@ -11,10 +12,7 @@ namespace Artemis.DAL public static class SettingsProvider { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); - - private static readonly string SettingsFolder = - Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\settings"; - + private static readonly string SettingsFolder = GeneralHelpers.DataFolder + "settings"; private static readonly List Settings = new List(); /// @@ -35,9 +33,7 @@ namespace Artemis.DAL try { - var loadSettings = (IArtemisSettings) JsonConvert - .DeserializeObject(File.ReadAllText(SettingsFolder + $@"\{typeof(T)}.json")); - + var loadSettings = (IArtemisSettings) JsonConvert.DeserializeObject(File.ReadAllText(SettingsFolder + $"{typeof(T)}.json")); if (loadSettings == null) { loadSettings = (IArtemisSettings) new T(); @@ -80,7 +76,7 @@ namespace Artemis.DAL return; } - File.WriteAllText(SettingsFolder + $@"\{artemisSettings.GetType()}.json", json); + File.WriteAllText(SettingsFolder + $"{artemisSettings.GetType()}.json", json); } /// diff --git a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs index fe3b6faa5..e76416a7d 100644 --- a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs +++ b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs @@ -40,8 +40,7 @@ namespace Artemis.Modules.Games.Witcher3 public override void Enable() { // Ensure the config file is found - var witcherSettings = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + - @"\The Witcher 3\user.settings"; + var witcherSettings = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "\\The Witcher 3\\user.settings"; if (File.Exists(witcherSettings)) _witcherSettings = witcherSettings; diff --git a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs index b729f19a3..17b0e77a0 100644 --- a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs +++ b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3ViewModel.cs @@ -1,5 +1,4 @@ -using System; -using System.Diagnostics; +using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; @@ -14,8 +13,7 @@ namespace Artemis.Modules.Games.Witcher3 { public sealed class Witcher3ViewModel : ModuleViewModel { - public Witcher3ViewModel(MainManager mainManager, [Named(nameof(Witcher3Model))] ModuleModel moduleModel, - IKernel kernel) : base(mainManager, moduleModel, kernel) + public Witcher3ViewModel(MainManager mainManager, [Named(nameof(Witcher3Model))] ModuleModel moduleModel, IKernel kernel) : base(mainManager, moduleModel, kernel) { DisplayName = "The Witcher 3"; } @@ -54,11 +52,9 @@ namespace Artemis.Modules.Games.Witcher3 using (var archive = new ZipArchive(stream)) { // Look for any conflicting mods - if (Directory.Exists(dialog.SelectedPath + @"\mods")) + if (Directory.Exists(dialog.SelectedPath + "\\mods")) { - var file = Directory.GetFiles(dialog.SelectedPath + @"\mods", "playerWitcher.ws", - SearchOption.AllDirectories) - .FirstOrDefault(); + var file = Directory.GetFiles(dialog.SelectedPath + "\\mods", "playerWitcher.ws", SearchOption.AllDirectories).FirstOrDefault(); if (file != null) if (!file.Contains("modArtemis")) { @@ -70,15 +66,9 @@ namespace Artemis.Modules.Games.Witcher3 if (!viewHelp.Value) return; - // Put the mod in the documents folder instead - // Create the directory structure - var folder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + - @"\Artemis"; - - archive.ExtractToDirectory(folder + @"witcher3-mod", true); - - System.Diagnostics.Process.Start( - new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3")); + // Put the mod in the data folder instead, not user friendly but access to documents is unsure + archive.ExtractToDirectory(GeneralHelpers.DataFolder + "witcher3-mod", true); + System.Diagnostics.Process.Start(new ProcessStartInfo("https://github.com/SpoinkyNL/Artemis/wiki/The-Witcher-3")); return; } } diff --git a/Artemis/Artemis/Utilities/DataReaders/DllManager.cs b/Artemis/Artemis/Utilities/DataReaders/DllManager.cs index e31be1b13..8fbb63471 100644 --- a/Artemis/Artemis/Utilities/DataReaders/DllManager.cs +++ b/Artemis/Artemis/Utilities/DataReaders/DllManager.cs @@ -29,8 +29,8 @@ namespace Artemis.Utilities.DataReaders #region Logitech - private static readonly string LogitechPath = @"C:\Program Files\Logitech Gaming Software\SDK\LED\x64\"; - private static readonly string DllPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\dll"; + private static readonly string LogitechPath = "C:\\Program Files\\Logitech Gaming Software\\SDK\\LED\\x64\\"; + private static readonly string DllPath = GeneralHelpers.DataFolder + "dll\\"; public static void PlaceLogitechDll() { @@ -40,14 +40,14 @@ namespace Artemis.Utilities.DataReaders // Key doesn't exist yet on systems without LGS installed var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true) ?? Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true); - - key.SetValue(null, DllPath + @"\LogitechLed.dll"); + + key.SetValue(null, DllPath + "LogitechLed.dll"); // Make sure the fake DLL is in place if (!Directory.Exists(DllPath)) Directory.CreateDirectory(DllPath); - if (!File.Exists(DllPath + @"\LogitechLed.dll")) - File.WriteAllBytes(DllPath + @"\LogitechLED.dll", Resources.LogitechLED); + if (!File.Exists(DllPath + "LogitechLed.dll")) + File.WriteAllBytes(DllPath + "LogitechLED.dll", Resources.LogitechLED); } catch (Exception e) { @@ -59,9 +59,9 @@ namespace Artemis.Utilities.DataReaders { // Change the registry key to point to the real DLL var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Classes\CLSID\{a6519e67-7632-4375-afdf-caa889744403}\ServerBinary", true); - key?.SetValue(null, LogitechPath + @"\LogitechLed.dll"); + key?.SetValue(null, LogitechPath + "LogitechLed.dll"); } #endregion } -} +} \ No newline at end of file diff --git a/Artemis/Artemis/Utilities/GeneralHelpers.cs b/Artemis/Artemis/Utilities/GeneralHelpers.cs index 526ed7a65..241d42518 100644 --- a/Artemis/Artemis/Utilities/GeneralHelpers.cs +++ b/Artemis/Artemis/Utilities/GeneralHelpers.cs @@ -13,6 +13,29 @@ namespace Artemis.Utilities { public static class GeneralHelpers { + public static string DataFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\Artemis\\"; + + public static void SetupDataFolder() + { + if (!Directory.Exists(DataFolder)) + Directory.CreateDirectory(DataFolder); + + var oldDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Artemis\\"; + + try + { + if (!Directory.Exists(oldDataFolder)) + return; + + // Migrate the old Artemis folder if it's present and access to it can be gained + MoveDirectory(oldDataFolder, DataFolder); + } + catch (Exception) + { + // ignored, could be blocked, in that case tough luck! + } + } + /// /// Perform a deep Copy of the object, using Json as a serialisation method. /// @@ -66,7 +89,6 @@ namespace Artemis.Utilities // At this point the loop is in the item type contained in the list PropertyCollection parent; if (path.Contains("Item") && inList) - { parent = new PropertyCollection { Type = propInfo.PropertyType.Name, @@ -74,9 +96,7 @@ namespace Artemis.Utilities Display = $"{path.Replace("Item.", "").Replace(".", " → ")}{propInfo.Name}", Path = $"{path.Replace("Item.", "")}{propInfo.Name}" }; - } else - { parent = new PropertyCollection { Type = propInfo.PropertyType.Name, @@ -84,7 +104,6 @@ namespace Artemis.Utilities Display = $"{path.Replace(".", " → ")}{propInfo.Name}", Path = $"{path}{propInfo.Name}" }; - } if (propInfo.PropertyType.BaseType?.Name == "Enum") { @@ -154,6 +173,27 @@ namespace Artemis.Utilities return (T) Enum.Parse(typeof(T), value, true); } + public static void MoveDirectory(string source, string target) + { + var sourcePath = source.TrimEnd('\\', ' '); + var targetPath = target.TrimEnd('\\', ' '); + var files = Directory.EnumerateFiles(sourcePath, "*", SearchOption.AllDirectories).GroupBy(Path.GetDirectoryName); + foreach (var folder in files) + { + var targetFolder = folder.Key.Replace(sourcePath, targetPath); + Directory.CreateDirectory(targetFolder); + foreach (var file in folder) + { + var fileName = Path.GetFileName(file); + if (fileName == null) continue; + var targetFile = Path.Combine(targetFolder, fileName); + if (File.Exists(targetFile)) File.Delete(targetFile); + File.Move(file, targetFile); + } + } + Directory.Delete(source, true); + } + public struct PropertyCollection { public string Display { get; set; } @@ -169,4 +209,4 @@ namespace Artemis.Utilities public string DisplayType { get; set; } } } -} +} \ No newline at end of file diff --git a/Artemis/Artemis/Utilities/Updater.cs b/Artemis/Artemis/Utilities/Updater.cs index 4d5c3fd5e..48dc1efe3 100644 --- a/Artemis/Artemis/Utilities/Updater.cs +++ b/Artemis/Artemis/Utilities/Updater.cs @@ -119,7 +119,7 @@ namespace Artemis.Utilities // Ensure the update folder exists var artemisFolder = AppDomain.CurrentDomain.BaseDirectory.Substring(0, AppDomain.CurrentDomain.BaseDirectory.Length - 1); - var updateFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Artemis\\updates"; + var updateFolder = GeneralHelpers.DataFolder + "updates"; var updatePath = updateFolder + "\\" + releaseFile["name"].Value(); if (!Directory.Exists(updateFolder)) Directory.CreateDirectory(updateFolder); diff --git a/Artemis/Artemis/ViewModels/DebugViewModel.cs b/Artemis/Artemis/ViewModels/DebugViewModel.cs index 9d6ac8855..3f3dae282 100644 --- a/Artemis/Artemis/ViewModels/DebugViewModel.cs +++ b/Artemis/Artemis/ViewModels/DebugViewModel.cs @@ -96,8 +96,7 @@ namespace Artemis.ViewModels public void OpenLog() { // Get the logging directory - var logDir = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) - + @"\Artemis\logs"); + var logDir = new DirectoryInfo(GeneralHelpers.DataFolder + "logs"); // Get the newest log file var currentLog = logDir.GetFiles().OrderByDescending(f => f.LastWriteTime).FirstOrDefault(); // Open the file with the user's default program diff --git a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs index ff32c2f5d..98354e784 100644 --- a/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs +++ b/Artemis/Artemis/ViewModels/Flyouts/FlyoutSettingsViewModel.cs @@ -227,7 +227,7 @@ namespace Artemis.ViewModels.Flyouts public void ShowLogs() { - var logPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Artemis\logs"; + var logPath = GeneralHelpers.DataFolder + "logs"; System.Diagnostics.Process.Start(logPath); }