diff --git a/HeliosPlus/GameLibraries/Game.cs b/HeliosPlus/GameLibraries/Game.cs new file mode 100644 index 0000000..b221650 --- /dev/null +++ b/HeliosPlus/GameLibraries/Game.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HeliosPlus.GameLibraries +{ + public class Game + { + + #region Properties + public virtual uint Id { get; set; } + + public virtual SupportedGameLibrary GameLibrary { get; } + + public virtual bool IsRunning { get; set; } + + public virtual bool IsUpdating { get; set; } + + public virtual string Name { get; set; } + + public virtual string ExePath { get; set; } + + public virtual string IconPath { get; set; } + + public virtual string Directory { get; set; } + + public virtual string Executable { get; set; } + + public virtual string ProcessName { get; set; } + + #endregion + + + #region Methods + public virtual bool CopyTo(SteamGame steamGame) + { + return true; + } + #endregion + } +} diff --git a/HeliosPlus/GameLibraries/SteamGame.cs b/HeliosPlus/GameLibraries/SteamGame.cs index 25a0cd3..30cbe3e 100644 --- a/HeliosPlus/GameLibraries/SteamGame.cs +++ b/HeliosPlus/GameLibraries/SteamGame.cs @@ -29,7 +29,7 @@ using System.Diagnostics; namespace HeliosPlus.GameLibraries { - public class SteamGame + public class SteamGame : Game { /*private static string SteamLibrary.SteamExe; private static string SteamLibrary.SteamPath; @@ -39,7 +39,8 @@ namespace HeliosPlus.GameLibraries private string _gameRegistryKey; private uint _steamGameId; private string _steamGameName; - private string _steamGamePath; + private string _steamGameExePath; + private string _steamGameDir; private string _steamGameExe; private string _steamGameProcessName; private string _steamGameIconPath; @@ -61,34 +62,53 @@ namespace HeliosPlus.GameLibraries } - public SteamGame(uint steamGameId, string steamGameName, string steamGamePath, string steamGameExe, string steamGameIconPath) + public SteamGame(uint steamGameId, string steamGameName, string steamGameExePath, string steamGameIconPath) { _gameRegistryKey = $@"{SteamLibrary.SteamAppsRegistryKey}\\{steamGameId}"; _steamGameId = steamGameId; _steamGameName = steamGameName; - _steamGamePath = steamGamePath; - _steamGameExe = steamGameExe; - _steamGameProcessName = Path.GetFileNameWithoutExtension(_steamGameExe); + _steamGameExePath = steamGameExePath; + _steamGameDir = Path.GetDirectoryName(steamGameExePath); + _steamGameExe = Path.GetFileName(_steamGameExePath); + _steamGameProcessName = Path.GetFileNameWithoutExtension(_steamGameExePath); _steamGameIconPath = steamGameIconPath; } - public uint GameId { + public override uint Id { get => _steamGameId; set => _steamGameId = value; } - public SupportedGameLibrary GameLibrary { + public override string Name + { + get => _steamGameName; + set => _steamGameName = value; + } + + public override SupportedGameLibrary GameLibrary { get => SupportedGameLibrary.Steam; } - public string GameIconPath { + public override string IconPath { get => _steamGameIconPath; set => _steamGameIconPath = value; } - - public bool IsRunning + + public override string ExePath + { + get => _steamGameExePath; + set => _steamGameExePath = value; + } + + public override string Directory + { + get => _steamGameExePath; + set => _steamGameExePath = value; + } + + public override bool IsRunning { get { @@ -123,12 +143,12 @@ namespace HeliosPlus.GameLibraries bool isRunning = Process.GetProcessesByName(_steamGameProcessName) .FirstOrDefault(p => p.MainModule.FileName - .StartsWith(GamePath,StringComparison.OrdinalIgnoreCase)) != default(Process); + .StartsWith(ExePath,StringComparison.OrdinalIgnoreCase)) != default(Process); return isRunning; } } - public bool IsUpdating + public override bool IsUpdating { get { @@ -163,26 +183,16 @@ namespace HeliosPlus.GameLibraries } } - public string GameName { - get => _steamGameName; - set => _steamGameName = value; - } - - public string GamePath { - get => _steamGamePath; - set => _steamGamePath = value; - } - public bool CopyTo(SteamGame steamGame) { if (!(steamGame is SteamGame)) return false; // Copy all the game data over to the other game - steamGame.GameIconPath = GameIconPath; - steamGame.GameId = GameId; - steamGame.GameName = GameName; - steamGame.GamePath = GamePath; + steamGame.IconPath = IconPath; + steamGame.Id = Id; + steamGame.Name = Name; + steamGame.ExePath = ExePath; return true; } diff --git a/HeliosPlus/GameLibraries/SteamLibrary.cs b/HeliosPlus/GameLibraries/SteamLibrary.cs index 86bd98d..b3a4e2a 100644 --- a/HeliosPlus/GameLibraries/SteamLibrary.cs +++ b/HeliosPlus/GameLibraries/SteamLibrary.cs @@ -48,8 +48,6 @@ namespace HeliosPlus.GameLibraries _steamPath = _steamPath.Replace('/', '\\'); } - // Load the Shortcuts from storage - LoadInstalledSteamGames(); } #endregion @@ -60,7 +58,7 @@ namespace HeliosPlus.GameLibraries { // Load the Steam Games from Steam Client if needed if (_allSteamGames == null) - LoadInstalledSteamGames(); + LoadInstalledGames(); return _allSteamGames; } } @@ -132,7 +130,7 @@ namespace HeliosPlus.GameLibraries if (ContainsSteamGame(steamGame)) { // We update the existing Shortcut with the data over - SteamGame steamGameToUpdate = GetSteamGame(steamGame.GameId.ToString()); + SteamGame steamGameToUpdate = GetSteamGame(steamGame.Id.ToString()); steamGame.CopyTo(steamGameToUpdate); } else @@ -157,7 +155,7 @@ namespace HeliosPlus.GameLibraries return false; // Remove the steamGame from the list. - int numRemoved = _allSteamGames.RemoveAll(item => item.GameId.Equals(steamGame.GameId)); + int numRemoved = _allSteamGames.RemoveAll(item => item.Id.Equals(steamGame.Id)); if (numRemoved == 1) { @@ -178,9 +176,9 @@ namespace HeliosPlus.GameLibraries int numRemoved; Match match = Regex.Match(steamGameNameOrUuid, steamAppIdRegex, RegexOptions.IgnoreCase); if (match.Success) - numRemoved = _allSteamGames.RemoveAll(item => steamGameNameOrUuid.Equals(Convert.ToUInt32(item.GameId))); + numRemoved = _allSteamGames.RemoveAll(item => steamGameNameOrUuid.Equals(Convert.ToUInt32(item.Id))); else - numRemoved = _allSteamGames.RemoveAll(item => steamGameNameOrUuid.Equals(item.GameName)); + numRemoved = _allSteamGames.RemoveAll(item => steamGameNameOrUuid.Equals(item.Name)); if (numRemoved == 1) return true; @@ -199,7 +197,7 @@ namespace HeliosPlus.GameLibraries foreach (SteamGame testSteamGame in _allSteamGames) { - if (testSteamGame.GameId.Equals(steamGame.GameId)) + if (testSteamGame.Id.Equals(steamGame.Id)) return true; } @@ -217,7 +215,7 @@ namespace HeliosPlus.GameLibraries { foreach (SteamGame testSteamGame in _allSteamGames) { - if (steamGameNameOrUuid.Equals(Convert.ToUInt32(testSteamGame.GameId))) + if (steamGameNameOrUuid.Equals(Convert.ToUInt32(testSteamGame.Id))) return true; } @@ -226,7 +224,7 @@ namespace HeliosPlus.GameLibraries { foreach (SteamGame testSteamGame in _allSteamGames) { - if (steamGameNameOrUuid.Equals(testSteamGame.GameName)) + if (steamGameNameOrUuid.Equals(testSteamGame.Name)) return true; } @@ -240,7 +238,7 @@ namespace HeliosPlus.GameLibraries { foreach (SteamGame testSteamGame in _allSteamGames) { - if (steamGameId == testSteamGame.GameId) + if (steamGameId == testSteamGame.Id) return true; } @@ -260,7 +258,7 @@ namespace HeliosPlus.GameLibraries { foreach (SteamGame testSteamGame in _allSteamGames) { - if (steamGameNameOrUuid.Equals(Convert.ToUInt32(testSteamGame.GameId))) + if (steamGameNameOrUuid.Equals(Convert.ToUInt32(testSteamGame.Id))) return testSteamGame; } @@ -269,7 +267,7 @@ namespace HeliosPlus.GameLibraries { foreach (SteamGame testSteamGame in _allSteamGames) { - if (steamGameNameOrUuid.Equals(testSteamGame.GameName)) + if (steamGameNameOrUuid.Equals(testSteamGame.Name)) return testSteamGame; } @@ -283,7 +281,7 @@ namespace HeliosPlus.GameLibraries { foreach (SteamGame testSteamGame in _allSteamGames) { - if (steamGameId == testSteamGame.GameId) + if (steamGameId == testSteamGame.Id) return testSteamGame; } @@ -291,7 +289,7 @@ namespace HeliosPlus.GameLibraries } - private static bool LoadInstalledSteamGames() + public static bool LoadInstalledGames() { try { @@ -547,7 +545,7 @@ namespace HeliosPlus.GameLibraries } // And we add the Game to the list of games we have! - _allSteamGames.Add(new SteamGame(steamGameId, steamGameName, steamGameInstallDir, steamGameExe, steamGameIconPath)); + _allSteamGames.Add(new SteamGame(steamGameId, steamGameName, steamGameExe, steamGameIconPath)); } } diff --git a/HeliosPlus/HeliosPlus.csproj b/HeliosPlus/HeliosPlus.csproj index 8d73d02..b0c2d19 100644 --- a/HeliosPlus/HeliosPlus.csproj +++ b/HeliosPlus/HeliosPlus.csproj @@ -73,6 +73,7 @@ + diff --git a/HeliosPlus/Program.cs b/HeliosPlus/Program.cs index ac89a2f..f66ad9e 100644 --- a/HeliosPlus/Program.cs +++ b/HeliosPlus/Program.cs @@ -104,6 +104,8 @@ namespace HeliosPlus { return 0; }); + // Try to load all the games in parallel to this process + Task.Run(() => LoadGamesInBackground()); try { @@ -418,8 +420,93 @@ namespace HeliosPlus { } } + public static bool LoadGamesInBackground() + { + + Debug.WriteLine("Program/LoadGamesInBackground : Starting"); + // Now lets prepare loading all the Steam games we have installed + Task loadSteamGamesTask = new Task(() => + { + // Load Steam library games + Console.WriteLine("Program/LoadGamesInBackground : Loading Installed Steam Games "); + if (!HeliosPlus.GameLibraries.SteamLibrary.LoadInstalledGames()) + { + // Somehow return that this profile topology didn't apply + throw new LoadingInstalledGamesException("Program/LoadGamesInBackground: Cannot load installed Steam Games!"); + } + }); + + // Now lets prepare loading all the Uplay games we have installed + Task loadUplayGamesTask = new Task(() => + { + // Load Uplay library games + Console.WriteLine("Program/LoadGamesInBackground : Loading Installed Uplay Games "); + /* if (!HeliosPlus.GameLibraries.UplayLibrary.LoadInstalledGames()) + { + // Somehow return that this profile topology didn't apply + throw new LoadingInstalledGamesException("Program/LoadGamesInBackground: Cannot load installed Uplay Games!"); + } + */ + + }); + + // Store all the tasks in an array so we can wait on them later + Task[] loadGamesTasks = new Task[2]; + loadGamesTasks[0] = loadSteamGamesTask; + loadGamesTasks[1] = loadUplayGamesTask; + + Console.WriteLine("Program/LoadGamesInBackground : Running tasks"); + // Go through and start all the tasks + foreach (Task loadGameTask in loadGamesTasks) + loadGameTask.Start(); + + try + { + Console.WriteLine("Program/LoadGamesInBackground : Waiting for tasks to finish"); + Task.WaitAll(loadGamesTasks); + Console.WriteLine("Program/LoadGamesInBackground : All tasks completed!"); + } + catch (AggregateException ae) + { + Console.WriteLine("Program/LoadGamesInBackground : Task exception!"); + foreach (var e in ae.InnerExceptions) + { + // Handle the custom exception. + if (e is LoadingInstalledGamesException) + { + Console.WriteLine(e.Message); + } + // Rethrow any other exception. + else + { + throw; + } + } + } + + bool failedTask = false; + foreach (var loadGameTask in loadGamesTasks) + { + Console.WriteLine($"Program/LoadGamesInBackground: LoadGameTask #{loadGameTask.Id}: {loadGameTask.Status}"); + if (loadGameTask.Exception != null) + { + failedTask = true; + foreach (var ex in loadGameTask.Exception.InnerExceptions) + Console.WriteLine(" {0}: {1}", ex.GetType().Name, + ex.Message); + } + } + + if (failedTask) + return false; + + return true; + + } + } + public class ApplyTopologyException : Exception { public ApplyTopologyException(String message) : base(message) @@ -431,4 +518,10 @@ namespace HeliosPlus { public ApplyPathInfoException(String message) : base(message) { } } + + public class LoadingInstalledGamesException : Exception + { + public LoadingInstalledGamesException(String message) : base(message) + { } + } } \ No newline at end of file diff --git a/HeliosPlus/ShortcutItem.cs b/HeliosPlus/ShortcutItem.cs index a3f96c1..7078274 100644 --- a/HeliosPlus/ShortcutItem.cs +++ b/HeliosPlus/ShortcutItem.cs @@ -24,6 +24,7 @@ using System.Diagnostics; using System.Threading; using HeliosPlus.InterProcess; using HeliosPlus.UIForms; +using ComponentFactory.Krypton.Toolkit; namespace HeliosPlus { @@ -50,30 +51,265 @@ namespace HeliosPlus public bool CloseOnFinish; } + public struct Executable + { + public string DifferentExecutableToMonitor; + public string ExecutableNameAndPath; + public uint ExecutableTimeout; + public string ExecutableArguments; + public bool ExecutableArgumentsRequired; + public bool ProcessNameToMonitorUsesExecutable; + } + + public struct GameStruct + { + public Game GameToPlay; + public uint StartTimeout; + public string GameArguments; + public bool GameArgumentsRequired; + } + public class ShortcutItem { //private static List _allSavedShortcuts = new List(); //private MultiIcon _shortcutIcon, _originalIcon = null; - private Bitmap _shortcutBitmap, _originalBitmap = null; - private ProfileItem _profileToUse = null; - private string _originalIconPath = ""; //private string _savedShortcutIconCacheFilename = ""; + private string _profileUuid = ""; + private ProfileItem _profileToUse; private string _uuid = ""; private string _name = ""; - //private uint _id = 0; - private string _profileUuid = ""; - private bool _isPossible = false; + private ShortcutCategory _category = ShortcutCategory.NoGame; + private string _differentExecutableToMonitor; + private string _executableNameAndPath = ""; + private string _executableArguments; + private bool _executableArgumentsRequired; + private bool _processNameToMonitorUsesExecutable; + private uint _gameAppId; + private string _gameName; + private SupportedGameLibrary _gameLibrary; + private uint _startTimeout; + private string _gameArguments; + private bool _gameArgumentsRequired; + private ShortcutPermanence _permanence; + private bool _autoName; + private bool _isPossible; + private List _startPrograms; + public string _originalIconPath; + private Bitmap _shortcutBitmap, _originalBitmap; + public ShortcutItem() { + // Create a new UUID for the shortcut if one wasn't created already + if (String.IsNullOrWhiteSpace(_uuid)) + _uuid = Guid.NewGuid().ToString("D"); + + // Autocreate a name for the shortcut if AutoName is on + // (and if we have a profile to use) + if (AutoName && _profileToUse is ProfileItem) + { + // If Autoname is on, and then lets autoname it! + // That populates all the right things + AutoSuggestShortcutName(); + } + } - public ShortcutItem(ProfileItem profile) : this() + public ShortcutItem( + string name, + ProfileItem profile, + uint gameAppId, + string gameName, + SupportedGameLibrary gameLibrary, + uint gameTimeout, + string gameArguments, + bool gameArgumentsRequired, + ShortcutPermanence permanence, + string originalIconPath, + List startPrograms = null, + bool autoName = true, + string uuid = "" + ) : this() { - ProfileToUse = profile; + _uuid = uuid; + _name = name; + _profileToUse = profile; + _category = ShortcutCategory.Game; + _profileToUse = profile; + _gameAppId = gameAppId; + _gameName = gameName; + _gameLibrary = gameLibrary; + _startTimeout = gameTimeout; + _gameArguments = gameArguments; + _gameArgumentsRequired = gameArgumentsRequired; + _permanence = permanence; + _autoName = autoName; + _startPrograms = startPrograms; + _originalIconPath = originalIconPath; + + // Now we need to find and populate the profileUuid + _profileUuid = profile.UUID; + } + public ShortcutItem(string name, ProfileItem profile, GameStruct game, ShortcutPermanence permanence, string originalIconPath, + List startPrograms = null, bool autoName = true, string uuid = "") : this() + { + _uuid = uuid; + _name = name; + _profileToUse = profile; + _category = ShortcutCategory.Game; + _gameAppId = game.GameToPlay.Id; + _gameName = game.GameToPlay.Name; + _gameLibrary = game.GameToPlay.GameLibrary; + _startTimeout = game.StartTimeout; + _gameArguments = game.GameArguments; + _gameArgumentsRequired = game.GameArgumentsRequired; + _permanence = permanence; + _autoName = autoName; + _startPrograms = startPrograms; + _originalIconPath = originalIconPath; + + // Now we need to find and populate the profileUuid + _profileUuid = profile.UUID; + + } + + + + public ShortcutItem(string name, string profileUuid, GameStruct game, ShortcutPermanence permanence, string originalIconPath, + List startPrograms = null, bool autoName = true, string uuid = "") : this() + { + _uuid = uuid; + _name = name; + _profileUuid = profileUuid; + _category = ShortcutCategory.Game; + _gameAppId = game.GameToPlay.Id; + _gameName = game.GameToPlay.Name; + _gameLibrary = game.GameToPlay.GameLibrary; + _startTimeout = game.StartTimeout; + _gameArguments = game.GameArguments; + _gameArgumentsRequired = game.GameArgumentsRequired; + _gameArgumentsRequired = false; + _permanence = permanence; + _autoName = autoName; + _startPrograms = startPrograms; + _originalIconPath = originalIconPath; + + // Now we need to find and populate the profileToUse + foreach (ProfileItem profileToTest in ProfileRepository.AllProfiles) + { + if (profileToTest.UUID.Equals(_profileUuid,StringComparison.InvariantCultureIgnoreCase)) + { + _profileToUse = profileToTest; + break; + } + + } + + if (_profileToUse == null) + { + throw new Exception($"Trying to create a ShortcutItem and cannot find a loaded profile with UUID {uuid}."); + } + } + + public ShortcutItem( + string name, + ProfileItem profile, + string differentExecutableToMonitor, + string executableNameAndPath, + uint executableTimeout, + string executableArguments, + bool executableArgumentsRequired, + bool processNameToMonitorUsesExecutable, + ShortcutPermanence permanence, + string originalIconPath, + List startPrograms = null, + bool autoName = true, + string uuid = "" + ) : this() + { + _uuid = uuid; + _name = name; + _profileToUse = profile; + _category = ShortcutCategory.Application; + _differentExecutableToMonitor = differentExecutableToMonitor; + _executableNameAndPath = executableNameAndPath; + _startTimeout = executableTimeout; + _executableArguments = executableArguments; + _executableArgumentsRequired = executableArgumentsRequired; + _processNameToMonitorUsesExecutable = processNameToMonitorUsesExecutable; + _permanence = permanence; + _autoName = autoName; + _startPrograms = startPrograms; + _originalIconPath = originalIconPath; + + // Now we need to find and populate the profileUuid + _profileUuid = profile.UUID; + + } + + public ShortcutItem(string name, ProfileItem profile, Executable executable, ShortcutPermanence permanence, string originalIconPath, + List startPrograms = null, bool autoName = true, string uuid = "") : this() + { + _uuid = uuid; + _name = name; + _profileToUse = profile; + _category = ShortcutCategory.Application; + _differentExecutableToMonitor = executable.DifferentExecutableToMonitor; + _executableNameAndPath = executable.ExecutableNameAndPath; + _startTimeout = executable.ExecutableTimeout; + _executableArguments = executable.ExecutableArguments; + _executableArgumentsRequired = executable.ExecutableArgumentsRequired; + _processNameToMonitorUsesExecutable = executable.ProcessNameToMonitorUsesExecutable; + _permanence = permanence; + _autoName = autoName; + _startPrograms = startPrograms; + _originalIconPath = originalIconPath; + + // Now we need to find and populate the profileUuid + _profileUuid = profile.UUID; + + } + + public ShortcutItem(string name, string profileUuid, Executable executable, ShortcutPermanence permanence, string originalIconPath, + List startPrograms = null, bool autoName = true, string uuid = "") : this() + { + _uuid = uuid; + _name = name; + _profileUuid = profileUuid; + _category = ShortcutCategory.Application; + _differentExecutableToMonitor = executable.DifferentExecutableToMonitor; + _executableNameAndPath = executable.ExecutableNameAndPath; + _startTimeout = executable.ExecutableTimeout; + _executableArguments = executable.ExecutableArguments; + _executableArgumentsRequired = executable.ExecutableArgumentsRequired; + _processNameToMonitorUsesExecutable = executable.ProcessNameToMonitorUsesExecutable; + _permanence = permanence; + _autoName = autoName; + _startPrograms = startPrograms; + _originalIconPath = originalIconPath; + + // Now we need to find and populate the profileToUse + foreach (ProfileItem profileToTest in ProfileRepository.AllProfiles) + { + if (profileToTest.UUID.Equals(_profileUuid, StringComparison.InvariantCultureIgnoreCase)) + { + _profileToUse = profileToTest; + break; + } + + } + + if (_profileToUse == null) + { + throw new Exception($"Trying to create a ShortcutItem and cannot find a loaded profile with UUID {uuid}."); + } + + } + + public static Version Version { get => new Version(1, 0); @@ -83,8 +319,6 @@ namespace HeliosPlus { get { - if (String.IsNullOrWhiteSpace(_uuid)) - _uuid = Guid.NewGuid().ToString("D"); return _uuid; } set @@ -100,11 +334,6 @@ namespace HeliosPlus { get { - if (AutoName && _profileToUse is ProfileItem) - { - // If Autoname is on, and then lets autoname it! - AutoSuggestShortcutName(); - } return _name; } set @@ -113,23 +342,23 @@ namespace HeliosPlus } } - public bool AutoName { get; set; } = true; + public bool AutoName + { + get + { + return _autoName; + } + set + { + _autoName = value; + } + } [JsonIgnore] public ProfileItem ProfileToUse { get { - if (_profileToUse == null && !String.IsNullOrWhiteSpace(_profileUuid)) - foreach (ProfileItem profileToTest in ProfileRepository.AllProfiles) - { - if (profileToTest.UUID.Equals(_profileUuid)) - { - _profileToUse = profileToTest; - break; - } - - } return _profileToUse; } set @@ -138,9 +367,7 @@ namespace HeliosPlus { _profileToUse = value; _profileUuid = _profileToUse.UUID; - // And if we have the _originalBitmap we can also save the Bitmap overlay, but only if the ProfileToUse is set - if (_originalBitmap is Bitmap) - _shortcutBitmap = ToBitmapOverlay(_originalBitmap, ProfileToUse.ProfileTightestBitmap,256,256); + // We should try to set the Profile // And we rename the shortcut if the AutoName is on if (AutoName) AutoSuggestShortcutName(); @@ -151,8 +378,6 @@ namespace HeliosPlus public string ProfileUUID { get { - if (_profileUuid == null && _profileToUse is ProfileItem) - _profileUuid = _profileToUse.UUID; return _profileUuid; } set @@ -168,42 +393,198 @@ namespace HeliosPlus } } - public ShortcutPermanence Permanence { get; set; } = ShortcutPermanence.Temporary; + public ShortcutPermanence Permanence + { + get + { + return _permanence; + } - public ShortcutCategory Category { get; set; } = ShortcutCategory.Game; + set + { + _permanence = value; + } + } - public string DifferentExecutableToMonitor { get; set; } = ""; + public ShortcutCategory Category + { + get + { + return _category; + } - public string ExecutableNameAndPath { get; set; } = ""; + set + { + _category = value; + } + } - public uint ExecutableTimeout { get; set; } = 30; + public string DifferentExecutableToMonitor + { + get + { + return _differentExecutableToMonitor; + } - public string ExecutableArguments { get; set; } = ""; + set + { + _differentExecutableToMonitor = value; + } + } - public bool ExecutableArgumentsRequired { get; set; } = false; + public string ExecutableNameAndPath + { + get + { + return _executableNameAndPath; + } - public bool ProcessNameToMonitorUsesExecutable { get; set; } = true; + set + { + _executableNameAndPath = value; - public uint GameAppId { get; set; } = 0; + // If the executableNameandPath is set then we also want to update the originalIconPath + // so it's the path to the application. This will kick of the icon grabbing processes + if (!String.IsNullOrWhiteSpace(_originalIconPath)) + if (Category.Equals(ShortcutCategory.Application)) + _originalIconPath = value; - public string GameName { get; set; } = ""; + } + } - public SupportedGameLibrary GameLibrary { get; set; } = SupportedGameLibrary.Unknown; + public string ExecutableArguments + { + get + { + return _executableArguments; + } - public uint GameTimeout { get; set; } = 30; + set + { + _executableArguments = value; + } + } - public string GameArguments { get; set; } = ""; + public bool ExecutableArgumentsRequired + { + get + { + return _executableArgumentsRequired; + } - public bool GameArgumentsRequired { get; set; } = false; + set + { + _executableArgumentsRequired = value; + } + } - public List StartPrograms { get; set; } + public bool ProcessNameToMonitorUsesExecutable + { + get + { + return _processNameToMonitorUsesExecutable; + } + + set + { + _processNameToMonitorUsesExecutable = value; + } + } + + public uint GameAppId + { + get + { + return _gameAppId; + } + + set + { + _gameAppId = value; + } + } + + public string GameName + { + get + { + return _gameName; + } + + set + { + _gameName = value; + } + } + + public SupportedGameLibrary GameLibrary + { + get + { + return _gameLibrary; + } + + set + { + _gameLibrary = value; + } + } + + public uint StartTimeout + { + get + { + return _startTimeout; + } + + set + { + _startTimeout = value; + } + } + + public string GameArguments + { + get + { + return _gameArguments; + } + + set + { + _gameArguments = value; + } + } + + public bool GameArgumentsRequired + { + get + { + return _gameArgumentsRequired; + } + + set + { + _gameArgumentsRequired = value; + } + } + + public List StartPrograms + { + get + { + return _startPrograms; + } + + set + { + _startPrograms = value; + } + } public string OriginalIconPath { get { - if (String.IsNullOrEmpty(_originalIconPath)) - return null; - return _originalIconPath; } @@ -211,17 +592,9 @@ namespace HeliosPlus { _originalIconPath = value; - // We now force creation of the bitmap - // straight away, so we know it has already been done. - - /*if (Category == ShortcutCategory.Application) - _originalBitmap = ToBitmapFromExe(_originalIconPath); - else - _originalBitmap = ToBitmapFromIcon(_originalIconPath);*/ - - // And we do the same for the Bitmap overlay, but only if the ProfileToUse is set - //if (ProfileToUse is ProfileItem) - // _shortcutBitmap = ToBitmapOverlay(_originalBitmap, ProfileToUse.ProfileTightestBitmap, 256, 256); + // And we do the same for the OriginalBitmap + if (_originalBitmap == null) + _originalBitmap = ToBitmap(_originalIconPath); } } @@ -230,25 +603,17 @@ namespace HeliosPlus { get { - if (_originalBitmap is Bitmap) - return _originalBitmap; - else - { - if (String.IsNullOrEmpty(OriginalIconPath)) - return null; - - if (Category == ShortcutCategory.Application) - _originalBitmap = ToBitmapFromExe(OriginalIconPath); - else - _originalBitmap = ToBitmapFromIcon(OriginalIconPath); - - return _originalBitmap; - } + return _originalBitmap; } set { _originalBitmap = value; + + // And we do the same for the Bitmap overlay, but only if the ProfileToUse is set + if (_profileToUse is ProfileItem) + _shortcutBitmap = ToBitmapOverlay(_originalBitmap, _profileToUse.ProfileTightestBitmap, 256, 256); + } } @@ -257,25 +622,12 @@ namespace HeliosPlus { get { - if (_shortcutBitmap is Bitmap) - return _shortcutBitmap; - else - { - - if (ProfileToUse == null) - return null; - - if (OriginalBitmap == null) - return null; - - _shortcutBitmap = ToBitmapOverlay(_originalBitmap, ProfileToUse.ProfileTightestBitmap, 256, 256); - return _shortcutBitmap; - } + return _shortcutBitmap; } set { - _originalBitmap = value; + _shortcutBitmap = value; } } @@ -310,14 +662,13 @@ namespace HeliosPlus shortcut.Category = Category; shortcut.DifferentExecutableToMonitor = DifferentExecutableToMonitor; shortcut.ExecutableNameAndPath = ExecutableNameAndPath; - shortcut.ExecutableTimeout = ExecutableTimeout; shortcut.ExecutableArguments = ExecutableArguments; shortcut.ExecutableArgumentsRequired = ExecutableArgumentsRequired; shortcut.ProcessNameToMonitorUsesExecutable = ProcessNameToMonitorUsesExecutable; shortcut.GameAppId = GameAppId; shortcut.GameName = GameName; shortcut.GameLibrary = GameLibrary; - shortcut.GameTimeout = GameTimeout; + shortcut.StartTimeout = StartTimeout; shortcut.GameArguments = GameArguments; shortcut.GameArgumentsRequired = GameArgumentsRequired; shortcut.OriginalIconPath = OriginalIconPath; diff --git a/HeliosPlus/ShortcutRepository.cs b/HeliosPlus/ShortcutRepository.cs index 23fdc91..a3cd68f 100644 --- a/HeliosPlus/ShortcutRepository.cs +++ b/HeliosPlus/ShortcutRepository.cs @@ -547,7 +547,7 @@ namespace HeliosPlus { // Now wait a little while for all the processes we want to monitor to start up var ticks = 0; - while (ticks < shortcutToUse.ExecutableTimeout * 1000) + while (ticks < shortcutToUse.StartTimeout * 1000) { // Look for the processes with the ProcessName we want (which in Windows is the filename without the extension) processesToMonitor = System.Diagnostics.Process.GetProcessesByName(Path.GetFileNameWithoutExtension(shortcutToUse.DifferentExecutableToMonitor)).ToList(); @@ -630,7 +630,7 @@ namespace HeliosPlus { // Prepare to start the steam game using the URI interface // as used by Steam for it's own desktop shortcuts. - var address = $"steam://rungameid/{steamGameToRun.GameId}"; + var address = $"steam://rungameid/{steamGameToRun.Id}"; if (shortcutToUse.GameArgumentsRequired) { address += "/" + shortcutToUse.GameArguments; @@ -641,7 +641,7 @@ namespace HeliosPlus // Wait for Steam game to update if needed var ticks = 0; - while (ticks < shortcutToUse.GameTimeout * 1000) + while (ticks < shortcutToUse.StartTimeout * 1000) { if (steamGameToRun.IsRunning) { @@ -696,7 +696,7 @@ namespace HeliosPlus Thread.Sleep(300); } - Console.WriteLine($"{steamGameToRun.GameName} has been exited. Now continuing with cleanup tasks."); + Console.WriteLine($"{steamGameToRun.Name} has been exited. Now continuing with cleanup tasks."); } // Remove the status notification icon from the status area diff --git a/HeliosPlus/UIForms/ShortcutForm.cs b/HeliosPlus/UIForms/ShortcutForm.cs index dcd1a9b..f58d610 100644 --- a/HeliosPlus/UIForms/ShortcutForm.cs +++ b/HeliosPlus/UIForms/ShortcutForm.cs @@ -22,11 +22,15 @@ namespace HeliosPlus.UIForms private ProfileAdaptor _profileAdaptor; //private List _loadedProfiles = new List(); private ProfileItem _profileToUse= null; + private GameStruct _gameToUse; + private Executable _executableToUse; + private ShortcutPermanence _permanence = ShortcutPermanence.Temporary; + List _startPrograms = new List(); private ShortcutItem _shortcutToEdit = null; - private bool _isNewShortcut = false; + private bool _isNewShortcut = true; private bool _isUnsaved = false; private bool _loadedShortcut = false; - private bool _saveNameAutomatic = true; + private bool _autoName = true; private uint _gameId = 0; private string _uuid = ""; @@ -41,12 +45,12 @@ namespace HeliosPlus.UIForms // Create a new SHortcut if we are creating a new one // And set up the page (otherwise this is all set when we load an // existing Shortcut) - if (_shortcutToEdit == null) + /*if (_shortcutToEdit == null) { - _shortcutToEdit = new ShortcutItem(); - _isNewShortcut = true; + //_shortcutToEdit = new ShortcutItem(); + //_isNewShortcut = true; } - +*/ } @@ -366,69 +370,14 @@ namespace HeliosPlus.UIForms } - // Fill the Shortcut object with the bits we care about saving - // Save the autonaming setting - _shortcutToEdit.AutoName = cb_autosuggest.Checked; - - // Update the Executable args - _shortcutToEdit.ExecutableArguments = txt_args_executable.Text; - - // Update if the executable args are needed - _shortcutToEdit.ExecutableArgumentsRequired = cb_args_executable.Checked; - - // Update the Executable name and path - _shortcutToEdit.ExecutableNameAndPath = txt_executable.Text; - - // Update the executable timeout - _shortcutToEdit.ExecutableTimeout = Convert.ToUInt32(nud_timeout_executable.Value); - - // Update the game app id - _shortcutToEdit.GameAppId = _gameId; - - // Update the game args - _shortcutToEdit.GameArguments = txt_args_game.Text; - - // Update if the game args are needed - _shortcutToEdit.GameArgumentsRequired = cb_args_game.Checked; - - // Update what game library it's from - //_shortcutToEdit.GameLibrary = SupportedGameLibrary.Steam; - - // Update the Game Name - _shortcutToEdit.GameName = txt_game_name.Text; - - // Update the Game Timeout - _shortcutToEdit.GameTimeout = Convert.ToUInt32(nud_timeout_game.Value); - - // Update the Shortcut name - _shortcutToEdit.Name = txt_shortcut_save_name.Text; + // Set some values // Check the permanence requirements if (rb_switch_temp.Checked) - _shortcutToEdit.Permanence = ShortcutPermanence.Temporary; + _permanence = ShortcutPermanence.Temporary; if (rb_switch_permanent.Checked) - _shortcutToEdit.Permanence = ShortcutPermanence.Permanent; - - // Update the process name to monitor - if (!String.IsNullOrWhiteSpace(txt_alternative_executable.Text)) { - _shortcutToEdit.DifferentExecutableToMonitor = txt_alternative_executable.Text; - } - - if (rb_wait_alternative_executable.Checked && !String.IsNullOrWhiteSpace(txt_alternative_executable.Text)) - { - _shortcutToEdit.ProcessNameToMonitorUsesExecutable = true; - _shortcutToEdit.DifferentExecutableToMonitor = txt_alternative_executable.Text; - } - else - { - _shortcutToEdit.ProcessNameToMonitorUsesExecutable = false; - } - - // Update the profile to use - _shortcutToEdit.ProfileToUse = _profileToUse; - - List myStartPrograms = new List(); + _permanence = ShortcutPermanence.Permanent; // Save the start program 1 StartProgram myStartProgram = new StartProgram(); @@ -438,7 +387,7 @@ namespace HeliosPlus.UIForms myStartProgram.ExecutableArgumentsRequired = cb_start_program_pass_args1.Checked; myStartProgram.Arguments = txt_start_program_args1.Text; myStartProgram.CloseOnFinish = cb_start_program_close1.Checked; - myStartPrograms.Add(myStartProgram); + _startPrograms.Add(myStartProgram); myStartProgram = new StartProgram(); myStartProgram.Priority = 2; @@ -447,7 +396,7 @@ namespace HeliosPlus.UIForms myStartProgram.ExecutableArgumentsRequired = cb_start_program_pass_args2.Checked; myStartProgram.Arguments = txt_start_program_args2.Text; myStartProgram.CloseOnFinish = cb_start_program_close2.Checked; - myStartPrograms.Add(myStartProgram); + _startPrograms.Add(myStartProgram); myStartProgram = new StartProgram(); myStartProgram.Priority = 3; @@ -456,7 +405,7 @@ namespace HeliosPlus.UIForms myStartProgram.ExecutableArgumentsRequired = cb_start_program_pass_args3.Checked; myStartProgram.Arguments = txt_start_program_args3.Text; myStartProgram.CloseOnFinish = cb_start_program_close3.Checked; - myStartPrograms.Add(myStartProgram); + _startPrograms.Add(myStartProgram); myStartProgram = new StartProgram(); myStartProgram.Priority = 4; @@ -465,31 +414,80 @@ namespace HeliosPlus.UIForms myStartProgram.ExecutableArgumentsRequired = cb_start_program_pass_args4.Checked; myStartProgram.Arguments = txt_start_program_args4.Text; myStartProgram.CloseOnFinish = cb_start_program_close4.Checked; - myStartPrograms.Add(myStartProgram); + _startPrograms.Add(myStartProgram); - // Save the start programs to the shortcut - _shortcutToEdit.StartPrograms = myStartPrograms; - - // Update the Category as well as the OriginalIconPath - // (as we need the OriginalIconPath to run the SaveShortcutIconToCache method) + // Now we create the Shortcut Object ready to save + // If we're launching a game if (rb_launcher.Checked) - _shortcutToEdit.Category = ShortcutCategory.Game; + { + // If the game is a SteamGame + if(txt_game_launcher.Text == SupportedGameLibrary.Steam.ToString()) + { + // Find the SteamGame + _gameToUse = new GameStruct(); + _gameToUse.GameToPlay = (from steamGame in SteamLibrary.AllInstalledGames where steamGame.Id == _gameId select steamGame).First(); + _gameToUse.StartTimeout = Convert.ToUInt32(nud_timeout_game.Value); + _gameToUse.GameArguments = txt_args_game.Text; + _gameToUse.GameArgumentsRequired = cb_args_game.Checked; - if (txt_game_launcher.Text == SupportedGameLibrary.Steam.ToString()) - { - _shortcutToEdit.OriginalIconPath = (from steamGame in SteamLibrary.AllInstalledGames where steamGame.GameId == _shortcutToEdit.GameAppId select steamGame.GameIconPath).First(); - _shortcutToEdit.GameLibrary = SupportedGameLibrary.Steam; - } - /*else if (txt_game_launcher.Text == SupportedGameLibrary.Uplay.ToString()) - { - _shortcutToEdit.OriginalIconPath = (from uplayGame in UplayLibrary.AllInstalledGames where uplayGame.GameId == _shortcutToEdit.GameAppId select uplayGame.GameIconPath).First(); - _shortcutToEdit.GameLibrary = SupportedGameLibrary.Uplay; - }*/ + _shortcutToEdit = new ShortcutItem( + Name, + _profileToUse, + _gameToUse, + _permanence, + _gameToUse.GameToPlay.IconPath, + _startPrograms, + _autoName + ); + + } + // If the game is a SteamGame + /*else if (txt_game_launcher.Text == SupportedGameLibrary.Uplay.ToString()) + { + // Find the UplayGame + _steamGameToUse = (from UplayGame in SteamLibrary.AllInstalledGames where UplayGame.GameId == _shortcutToEdit.GameAppId).First(); + + _shortcutToEdit = new ShortcutItem( + Name, + _profileToUse, + _steamGameToUse, + _permanence, + _steamGameToUse.GameIconPath, + _startPrograms, + _autoName + ); + + }*/ + } else if (rb_standalone.Checked) { - _shortcutToEdit.Category = ShortcutCategory.Application; - } + _executableToUse = new Executable(); + _executableToUse.ExecutableArguments = txt_args_executable.Text; + _executableToUse.ExecutableArgumentsRequired = cb_args_executable.Checked; + _executableToUse.ExecutableNameAndPath = txt_executable.Text; + _executableToUse.ExecutableTimeout = Convert.ToUInt32(nud_timeout_executable.Value); + if (rb_wait_alternative_executable.Checked && !String.IsNullOrWhiteSpace(txt_alternative_executable.Text)) + { + _executableToUse.ProcessNameToMonitorUsesExecutable = true; + _executableToUse.DifferentExecutableToMonitor = txt_alternative_executable.Text; + } + else + { + _executableToUse.ProcessNameToMonitorUsesExecutable = false; + } + + _shortcutToEdit = new ShortcutItem( + Name, + _profileToUse, + _executableToUse, + _permanence, + _executableToUse.ExecutableNameAndPath, + _startPrograms, + _autoName + ); + } + // Add the Shortcut to the list of saved Shortcuts so it gets saved for later // but only if it's new... if it is an edit then it will already be in the list. ShortcutRepository.AddShortcut(_shortcutToEdit); @@ -539,7 +537,7 @@ namespace HeliosPlus.UIForms private void suggestShortcutName() { - if (_saveNameAutomatic && _profileToUse is ProfileItem) + if (_autoName && _profileToUse is ProfileItem) { if (rb_no_game.Checked) { @@ -659,6 +657,65 @@ namespace HeliosPlus.UIForms bool foundChosenProfileInLoadedProfiles = false; ProfileItem chosenProfile = null; + + // Load the Games ListView + foreach (var game in SteamLibrary.AllInstalledGames.OrderBy(game => game.Name)) + { + if (File.Exists(game.IconPath)) + { + try + { + if (game.IconPath.EndsWith(".ico")) + { + // if it's an icon try to load it as a bitmap + il_games.Images.Add(Image.FromFile(game.IconPath)); + } + else if (game.IconPath.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase) || game.IconPath.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase)) + { + // otherwise use IconExtractor + /*IconExtractor IconEx = new IconExtractor(game.GameIconPath); + Icon icoAppIcon = IconEx.GetIcon(0); // Because standard System.Drawing.Icon.ExtractAssociatedIcon() returns ONLY 32x32.*/ + + Icon icoAppIcon = Icon.ExtractAssociatedIcon(game.IconPath); + // We first try high quality icons + Bitmap extractedBitmap = ShortcutItem.ExtractVistaIcon(icoAppIcon); + if (extractedBitmap == null) + extractedBitmap = icoAppIcon.ToBitmap(); + il_games.Images.Add(extractedBitmap); + } + } + catch (Exception ex) + { + Console.WriteLine($"ShortcutForm exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); + il_games.Images.Add(Image.FromFile("Resources/Steam.ico")); + } + } + else + { + //(Icon)global::Calculate.Properties.Resources.ResourceManager.GetObject("Steam.ico"); + il_games.Images.Add(Image.FromFile("Resources/Steam.ico")); + } + + + if (!Visible) + { + return; + } + + lv_games.Items.Add(new ListViewItem + { + Text = game.Name, + Tag = game, + ImageIndex = il_games.Images.Count - 1 + }); + } + + + + // If it is a new Shortcut then we don't have to load anything! + if (_isNewShortcut) + return; + if (_shortcutToEdit is ShortcutItem && _shortcutToEdit.ProfileToUse is ProfileItem) { foreach (ProfileItem loadedProfile in ProfileRepository.AllProfiles) @@ -718,57 +775,6 @@ namespace HeliosPlus.UIForms } } - // Start finding the games and loading the Games ListView - foreach (var game in SteamLibrary.AllInstalledGames.OrderBy(game => game.GameName)) - { - if (File.Exists(game.GameIconPath)) - { - try - { - if (game.GameIconPath.EndsWith(".ico")) - { - // if it's an icon try to load it as a bitmap - il_games.Images.Add(Image.FromFile(game.GameIconPath)); - } - else if (game.GameIconPath.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase) || game.GameIconPath.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase)) - { - // otherwise use IconExtractor - /*IconExtractor IconEx = new IconExtractor(game.GameIconPath); - Icon icoAppIcon = IconEx.GetIcon(0); // Because standard System.Drawing.Icon.ExtractAssociatedIcon() returns ONLY 32x32.*/ - - Icon icoAppIcon = Icon.ExtractAssociatedIcon(game.GameIconPath); - // We first try high quality icons - Bitmap extractedBitmap = ShortcutItem.ExtractVistaIcon(icoAppIcon); - if (extractedBitmap == null) - extractedBitmap = icoAppIcon.ToBitmap(); - il_games.Images.Add(extractedBitmap); - } - } - catch (Exception ex) - { - Console.WriteLine($"ShortcutForm exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); - il_games.Images.Add(Image.FromFile("Resources/Steam.ico")); - } - } else - { - //(Icon)global::Calculate.Properties.Resources.ResourceManager.GetObject("Steam.ico"); - il_games.Images.Add(Image.FromFile("Resources/Steam.ico")); - } - - - if (!Visible) - { - return; - } - - lv_games.Items.Add(new ListViewItem - { - Text = game.GameName, - Tag = game, - ImageIndex = il_games.Images.Count - 1 - }); - } - // Now start populating the other fields _uuid = _shortcutToEdit.UUID; // Set if we launch App/Game/NoGame @@ -789,7 +795,7 @@ namespace HeliosPlus.UIForms txt_game_launcher.Text = _shortcutToEdit.GameLibrary.ToString(); txt_game_name.Text = _shortcutToEdit.GameName; _gameId = _shortcutToEdit.GameAppId; - nud_timeout_game.Value = _shortcutToEdit.GameTimeout; + nud_timeout_game.Value = _shortcutToEdit.StartTimeout; txt_args_game.Text = _shortcutToEdit.GameArguments; if (_shortcutToEdit.GameArgumentsRequired) { @@ -809,7 +815,7 @@ namespace HeliosPlus.UIForms // Set the executable items if we have them txt_executable.Text = _shortcutToEdit.ExecutableNameAndPath; - nud_timeout_executable.Value = _shortcutToEdit.ExecutableTimeout; + nud_timeout_executable.Value = _shortcutToEdit.StartTimeout; txt_args_executable.Text = _shortcutToEdit.ExecutableArguments; if (_shortcutToEdit.ExecutableArgumentsRequired) { @@ -950,12 +956,12 @@ namespace HeliosPlus.UIForms txt_game_name.Text = lv_games.SelectedItems[0].Text; foreach (SteamGame game in SteamLibrary.AllInstalledGames) { - if (game.GameName == txt_game_name.Text) + if (game.Name == txt_game_name.Text) { if (_loadedShortcut) _isUnsaved = true; txt_game_launcher.Text = game.GameLibrary.ToString(); - _gameId = game.GameId; + _gameId = game.Id; } } } @@ -1159,7 +1165,7 @@ namespace HeliosPlus.UIForms { if (_loadedShortcut) _isUnsaved = true; - _saveNameAutomatic = false; + _autoName = false; cb_autosuggest.Checked = false; } @@ -1169,11 +1175,11 @@ namespace HeliosPlus.UIForms _isUnsaved = true; if (cb_autosuggest.Checked) { - _saveNameAutomatic = true; + _autoName = true; suggestShortcutName(); } else - _saveNameAutomatic = false; + _autoName = false; } private string get_exe_file()