diff --git a/DisplayMagician/DisplayMagician.csproj b/DisplayMagician/DisplayMagician.csproj
index 2458831..3cec485 100644
--- a/DisplayMagician/DisplayMagician.csproj
+++ b/DisplayMagician/DisplayMagician.csproj
@@ -84,6 +84,7 @@
+
@@ -100,9 +101,9 @@
+
-
diff --git a/DisplayMagician/GameLibraries/OriginGame.cs b/DisplayMagician/GameLibraries/OriginGame.cs
index a66b115..3779dfb 100644
--- a/DisplayMagician/GameLibraries/OriginGame.cs
+++ b/DisplayMagician/GameLibraries/OriginGame.cs
@@ -3,9 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
-using System.Security;
using DisplayMagician.Resources;
-using Microsoft.Win32;
using System.Diagnostics;
namespace DisplayMagician.GameLibraries
@@ -29,21 +27,22 @@ namespace DisplayMagician.GameLibraries
}
- public OriginGame(string originGameId, string originGameName, string originGameExePath, string originGameIconPath)
+ public OriginGame(string OriginGameId, string OriginGameName, string OriginGameExePath, string OriginGameIconPath)
{
- _gameRegistryKey = $@"{OriginLibrary.OriginAppsRegistryKey}\\{originGameId}";
- _originGameId = originGameId;
- _originGameName = originGameName;
- _originGameExePath = originGameExePath;
- _originGameDir = Path.GetDirectoryName(originGameExePath);
+ //_gameRegistryKey = $@"{OriginLibrary.registryOriginInstallsKey}\\{OriginGameId}";
+ _originGameId = OriginGameId;
+ _originGameName = OriginGameName;
+ _originGameExePath = OriginGameExePath;
+ _originGameDir = Path.GetDirectoryName(OriginGameExePath);
_originGameExe = Path.GetFileName(_originGameExePath);
_originGameProcessName = Path.GetFileNameWithoutExtension(_originGameExePath);
- _originGameIconPath = originGameIconPath;
+ _originGameIconPath = OriginGameIconPath;
}
- public override string Id {
+ public override string Id
+ {
get => _originGameId;
set => _originGameId = value;
}
@@ -54,12 +53,14 @@ namespace DisplayMagician.GameLibraries
set => _originGameName = value;
}
- public override SupportedGameLibrary GameLibrary {
- get => SupportedGameLibrary.Origin;
+ public override SupportedGameLibrary GameLibrary
+ {
+ get => SupportedGameLibrary.Origin;
}
- public override string IconPath {
- get => _originGameIconPath;
+ public override string IconPath
+ {
+ get => _originGameIconPath;
set => _originGameIconPath = value;
}
@@ -84,21 +85,22 @@ namespace DisplayMagician.GameLibraries
foreach (Process gameProcess in gameProcesses)
{
try
- {
- if (gameProcess.MainModule.FileName.StartsWith(_originGameExePath))
+ {
+ if (gameProcess.ProcessName.Equals(_originGameProcessName))
numGameProcesses++;
}
catch (Exception ex)
{
- logger.Debug(ex, $"OriginGame/IsRunning: Accessing Process.MainModule caused exception. Trying GameUtils.GetMainModuleFilepath instead");
-
+ logger.Debug(ex, $"OriginGame/IsRunning: Accessing Process.ProcessName caused exception. Trying GameUtils.GetMainModuleFilepath instead");
// If there is a race condition where MainModule isn't available, then we
// instead try the much slower GetMainModuleFilepath (which does the same thing)
string filePath = GameUtils.GetMainModuleFilepath(gameProcess.Id);
if (filePath == null)
{
// if we hit this bit then GameUtils.GetMainModuleFilepath failed,
- // so we just skip that process
+ // so we just assume that the process is a game process
+ // as it matched the original process search
+ numGameProcesses++;
continue;
}
else
@@ -106,6 +108,7 @@ namespace DisplayMagician.GameLibraries
if (filePath.StartsWith(_originGameExePath))
numGameProcesses++;
}
+
}
}
if (numGameProcesses > 0)
@@ -115,7 +118,8 @@ namespace DisplayMagician.GameLibraries
}
}
- public override bool IsUpdating
+ // Have to do much more research to figure out how to detect when Origin is updating a game
+ /*public override bool IsUpdating
{
get
{
@@ -148,19 +152,19 @@ namespace DisplayMagician.GameLibraries
throw;
}
}
- }
+ }*/
- public bool CopyInto(OriginGame originGame)
+ public bool CopyTo(OriginGame OriginGame)
{
- if (!(originGame is OriginGame))
+ if (!(OriginGame is OriginGame))
return false;
// Copy all the game data over to the other game
- originGame.IconPath = IconPath;
- originGame.Id = Id;
- originGame.Name = Name;
- originGame.ExePath = ExePath;
- originGame.Directory = Directory;
+ OriginGame.IconPath = IconPath;
+ OriginGame.Id = Id;
+ OriginGame.Name = Name;
+ OriginGame.ExePath = ExePath;
+ OriginGame.Directory = Directory;
return true;
}
@@ -178,10 +182,10 @@ namespace DisplayMagician.GameLibraries
return name + " " + Language.Running;
}
- if (IsUpdating)
+ /*if (IsUpdating)
{
return name + " " + Language.Updating;
- }
+ }*/
return name;
}
diff --git a/DisplayMagician/GameLibraries/OriginLibrary.cs b/DisplayMagician/GameLibraries/OriginLibrary.cs
index 150a291..36a6a18 100644
--- a/DisplayMagician/GameLibraries/OriginLibrary.cs
+++ b/DisplayMagician/GameLibraries/OriginLibrary.cs
@@ -1,15 +1,14 @@
using System;
using System.Collections.Generic;
-using System.Text;
+using System.Linq;
using System.Text.RegularExpressions;
-//using ValveKeyValue;
using Microsoft.Win32;
-using Microsoft.QueryStringDotNET;
using System.IO;
using System.Security;
-using System.Diagnostics;
-using System.Net;
-using System.Linq;
+using System.Xml;
+using System.Xml.Linq;
+using System.Xml.XPath;
+using System.Web;
namespace DisplayMagician.GameLibraries
{
@@ -18,55 +17,70 @@ namespace DisplayMagician.GameLibraries
#region Class Variables
// Common items to the class
private static List _allOriginGames = new List();
- private static string originAppIdRegex = @"/^[0-9A-F]{1,10}$";
+ private static string OriginAppIdRegex = @"/^[0-9A-F]{1,10}$";
private static string _originExe;
private static string _originPath;
- private static string _originLocalContent = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),"Origin");
+ private static string _originLocalContent = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "Origin");
private static bool _isOriginInstalled = false;
+
+ //private static string _originConfigVdfFile;
+ internal static string registryOriginLauncherKey = @"SOFTWARE\WOW6432Node\Origin";
+ //internal static string registryOriginInstallsKey = @"SOFTWARE\WOW6432Node\Ubisoft\Launcher\Installs";
+ //internal static string registryOriginOpenCmdKey = @"SOFTWARE\Classes\Origin\Shell\Open\Command";
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
+
+
// Other constants that are useful
#endregion
private struct OriginAppInfo
{
- public int GameID;
+ public string GameID;
public string GameName;
- public List GameExes;
+ public string GameExePath;
public string GameInstallDir;
public string GameOriginIconPath;
}
-
+
#region Class Constructors
static OriginLibrary()
{
try
{
+ logger.Trace($"OriginLibrary/OriginLibrary: Origin launcher registry key = HKLM\\{registryOriginLauncherKey}");
// Find the OriginExe location, and the OriginPath for later
- using (var key = Registry.CurrentUser.OpenSubKey(OriginLibrary.OriginRegistryKey, RegistryKeyPermissionCheck.ReadSubTree))
- {
- _originExe = (string)key?.GetValue(@"OriginExe", string.Empty) ?? string.Empty;
- _originExe = _originExe.Replace('/', '\\');
- _originPath = (string)key?.GetValue(@"OriginPath", string.Empty) ?? string.Empty;
- _originPath = _originPath.Replace('/', '\\');
- }
+ RegistryKey OriginInstallKey = Registry.LocalMachine.OpenSubKey(registryOriginLauncherKey, RegistryKeyPermissionCheck.ReadSubTree);
+ if (OriginInstallKey == null)
+ return;
+ _originExe = OriginInstallKey.GetValue("ClientPath", @"C:\Program Files (x86)\Origin\Origin.exe").ToString();
+ _originPath = _originExe;
+ _originPath = _originPath.Replace(@"\Origin.exe", "");
if (File.Exists(_originExe))
+ {
+ logger.Info($"OriginLibrary/OriginLibrary: Origin library is installed in {_originPath}. Found {_originExe}");
_isOriginInstalled = true;
+ }
+ else
+ {
+ logger.Info($"OriginLibrary/OriginLibrary: Origin library is not installed!");
+ }
+
}
catch (SecurityException ex)
{
- logger.Warn(ex,"The user does not have the permissions required to read the Origin registry key.");
+ logger.Warn(ex, "OriginLibrary/OriginLibrary: The user does not have the permissions required to read the Origin ClientPath registry key.");
}
- catch (ObjectDisposedException ex)
+ catch(ObjectDisposedException ex)
{
- logger.Warn(ex, "The Microsoft.Win32.RegistryKey is closed when trying to access theOrigin registry key (closed keys cannot be accessed).");
+ logger.Warn(ex, "OriginLibrary/OriginLibrary: The Microsoft.Win32.RegistryKey is closed when trying to access the Origin ClientPath registry key (closed keys cannot be accessed).");
}
catch (IOException ex)
{
- logger.Warn(ex, "The Origin registry key has been marked for deletion so we cannot access the value during the OriginLibrary check.");
+ logger.Warn(ex, "OriginLibrary/OriginLibrary: The Origin ClientPath registry key has been marked for deletion so we cannot access the value dueing the OriginLibrary check.");
}
catch (UnauthorizedAccessException ex)
{
- logger.Warn(ex, "The user does not have the necessary registry rights to check whether Origin is installed.");
+ logger.Warn(ex, "OriginLibrary/OriginLibrary: The user does not have the necessary registry rights to check whether Origin is installed.");
}
}
#endregion
@@ -92,22 +106,6 @@ namespace DisplayMagician.GameLibraries
}
}
- /* public static string OriginRegistryKey
- {
- get
- {
- return _registryOriginKey;
- }
- }
-
- public static string OriginAppsRegistryKey
- {
- get
- {
- return _registryAppsKey;
- }
- }
-*/
public static string OriginExe
{
get
@@ -141,18 +139,20 @@ namespace DisplayMagician.GameLibraries
{
if (!(originGame is OriginGame))
return false;
-
+
// Doublecheck if it already exists
// Because then we just update the one that already exists
if (ContainsOriginGame(originGame))
{
+ logger.Debug($"OriginLibrary/AddOriginGame: Updating Origin game {originGame.Name} in our Origin library");
// We update the existing Shortcut with the data over
OriginGame originGameToUpdate = GetOriginGame(originGame.Id.ToString());
- originGame.CopyInto(originGameToUpdate);
+ originGame.CopyTo(originGameToUpdate);
}
else
{
- // Add the originGame to the list of originGames
+ logger.Debug($"OriginLibrary/AddOriginGame: Adding Origin game {originGame.Name} to our Origin library");
+ // Add the OriginGame to the list of OriginGames
_allOriginGames.Add(originGame);
}
@@ -171,54 +171,73 @@ namespace DisplayMagician.GameLibraries
if (!(originGame is OriginGame))
return false;
- // Remove the originGame from the list.
+ logger.Debug($"OriginLibrary/RemoveOriginGame: Removing Origin game {originGame.Name} from our Origin library");
+
+ // Remove the OriginGame from the list.
int numRemoved = _allOriginGames.RemoveAll(item => item.Id.Equals(originGame.Id));
if (numRemoved == 1)
{
+ logger.Debug($"OriginLibrary/RemoveOriginGame: Removed Origin game with name {originGame.Name}");
return true;
}
else if (numRemoved == 0)
+ {
+ logger.Debug($"OriginLibrary/RemoveOriginGame: Didn't remove Origin game with ID {originGame.Name} from the Origin Library");
return false;
+ }
else
throw new OriginLibraryException();
}
public static bool RemoveOriginGameById(string originGameId)
{
- if (originGameId.Equals("0"))
+ if (originGameId.Equals(0))
return false;
- // Remove the originGame from the list.
+ logger.Debug($"OriginLibrary/RemoveOriginGame2: Removing Origin game with ID {originGameId} from the Origin library");
+
+ // Remove the OriginGame from the list.
int numRemoved = _allOriginGames.RemoveAll(item => item.Id.Equals(originGameId));
if (numRemoved == 1)
{
+ logger.Debug($"OriginLibrary/RemoveOriginGame2: Removed Origin game with ID {originGameId}");
return true;
}
else if (numRemoved == 0)
+ {
+ logger.Debug($"OriginLibrary/RemoveOriginGame2: Didn't remove Origin game with ID {originGameId} from the Origin Library");
return false;
+ }
else
throw new OriginLibraryException();
}
-
public static bool RemoveOriginGame(string originGameNameOrId)
{
if (String.IsNullOrWhiteSpace(originGameNameOrId))
return false;
+ logger.Debug($"OriginLibrary/RemoveOriginGame3: Removing Origin game with Name or ID {originGameNameOrId} from the Origin library");
+
int numRemoved;
- Match match = Regex.Match(originGameNameOrId, originAppIdRegex, RegexOptions.IgnoreCase);
+ Match match = Regex.Match(originGameNameOrId, OriginAppIdRegex, RegexOptions.IgnoreCase);
if (match.Success)
numRemoved = _allOriginGames.RemoveAll(item => originGameNameOrId.Equals(item.Id));
else
numRemoved = _allOriginGames.RemoveAll(item => originGameNameOrId.Equals(item.Name));
if (numRemoved == 1)
+ {
+ logger.Debug($"OriginLibrary/RemoveOriginGame3: Removed Origin game with Name or UUID {originGameNameOrId} ");
return true;
+ }
else if (numRemoved == 0)
+ {
+ logger.Debug($"OriginLibrary/RemoveOriginGame3: Didn't remove Origin game with Name or UUID {originGameNameOrId} from the Origin Library");
return false;
+ }
else
throw new OriginLibraryException();
@@ -238,36 +257,6 @@ namespace DisplayMagician.GameLibraries
return false;
}
- public static bool ContainsOriginGame(string originGameNameOrUuid)
- {
- if (String.IsNullOrWhiteSpace(originGameNameOrUuid))
- return false;
-
-
- Match match = Regex.Match(originGameNameOrUuid, originAppIdRegex, RegexOptions.IgnoreCase);
- if (match.Success)
- {
- foreach (OriginGame testOriginGame in _allOriginGames)
- {
- if (originGameNameOrUuid.Equals(Convert.ToInt32(testOriginGame.Id)))
- return true;
- }
-
- }
- else
- {
- foreach (OriginGame testOriginGame in _allOriginGames)
- {
- if (originGameNameOrUuid.Equals(testOriginGame.Name))
- return true;
- }
-
- }
-
- return false;
-
- }
-
public static bool ContainsOriginGameById(string originGameId)
{
foreach (OriginGame testOriginGame in _allOriginGames)
@@ -276,7 +265,37 @@ namespace DisplayMagician.GameLibraries
return true;
}
-
+
+ return false;
+
+ }
+
+ public static bool ContainsOriginGame(string originGameNameOrId)
+ {
+ if (String.IsNullOrWhiteSpace(originGameNameOrId))
+ return false;
+
+
+ Match match = Regex.Match(originGameNameOrId, OriginAppIdRegex, RegexOptions.IgnoreCase);
+ if (match.Success)
+ {
+ foreach (OriginGame testOriginGame in _allOriginGames)
+ {
+ if (originGameNameOrId.Equals(Convert.ToInt32(testOriginGame.Id)))
+ return true;
+ }
+
+ }
+ else
+ {
+ foreach (OriginGame testOriginGame in _allOriginGames)
+ {
+ if (originGameNameOrId.Equals(testOriginGame.Name))
+ return true;
+ }
+
+ }
+
return false;
}
@@ -287,7 +306,7 @@ namespace DisplayMagician.GameLibraries
if (String.IsNullOrWhiteSpace(originGameNameOrId))
return null;
- Match match = Regex.Match(originGameNameOrId, originAppIdRegex, RegexOptions.IgnoreCase);
+ Match match = Regex.Match(originGameNameOrId, OriginAppIdRegex, RegexOptions.IgnoreCase);
if (match.Success)
{
foreach (OriginGame testOriginGame in _allOriginGames)
@@ -330,32 +349,19 @@ namespace DisplayMagician.GameLibraries
return parameters;
}
+
public static bool LoadInstalledGames()
{
try
{
- // Find the OriginExe location, and the OriginPath for later
- /*using (var key = Registry.CurrentUser.OpenSubKey(_registryOriginKey, RegistryKeyPermissionCheck.ReadSubTree))
- {
- _originExe = (string)key?.GetValue(@"OriginExe", string.Empty) ?? string.Empty;
- _originExe = _originExe.Replace('/', '\\');
- _originPath = (string)key?.GetValue(@"OriginPath", string.Empty) ?? string.Empty;
- _originPath = _originPath.Replace('/', '\\');
- }*/
-
if (!_isOriginInstalled)
{
// Origin isn't installed, so we return an empty list.
+ logger.Info($"OriginLibrary/LoadInstalledGames: Origin library is not installed");
return false;
}
- //Icon _originIcon = Icon.ExtractAssociatedIcon(_originExe);
- //IconExtractor originIconExtractor = new IconExtractor(_originExe);
- //Icon _originIcon = originIconExtractor.GetIcon(0);
- //MultiIcon _originIcon = new MultiIcon();
- //_originIcon.Load(_originExe);
-
var localContentPath = Path.Combine(_originLocalContent, "LocalContent");
//var games = new Dictionary();
@@ -366,24 +372,25 @@ namespace DisplayMagician.GameLibraries
{
try
{
- string gameId = Path.GetFileNameWithoutExtension(package);
- if (!gameId.StartsWith("Origin"))
+ OriginAppInfo originGame = new OriginAppInfo();
+ originGame.GameID = Path.GetFileNameWithoutExtension(package);
+ if (!originGame.GameID.StartsWith("Origin"))
{
// If the gameId doesn't start with origin, then we need to find it!
// Get game id by fixing file via adding : before integer part of the name
// for example OFB-EAST52017 converts to OFB-EAST:52017
- Match match = Regex.Match(gameId, @"^(.*?)(\d+)$");
+ Match match = Regex.Match(originGame.GameID, @"^(.*?)(\d+)$");
if (!match.Success)
{
logger.Warn("Failed to get game id from file " + package);
continue;
}
- gameId = match.Groups[1].Value + ":" + match.Groups[2].Value;
+ originGame.GameID = match.Groups[1].Value + ":" + match.Groups[2].Value;
}
// Now we get the rest of the game information out of the manifest file
- Dictionary manifestInfo = ParseOriginManifest(package);
+ Dictionary manifestInfo = ParseOriginManifest(package);
if (manifestInfo.ContainsKey("ddinitialdownload") && manifestInfo["ddinitialdownload"] == "1")
{
@@ -397,341 +404,254 @@ namespace DisplayMagician.GameLibraries
continue;
}
- string gamePath = null;
+ originGame.GameInstallDir = null;
if (manifestInfo.ContainsKey("dipinstallpath"))
{
- // This is where Origin has installed this game
- if (Directory.Exists(manifestInfo["downloading"]))
+ // This is where Origin has installed this game
+ originGame.GameInstallDir = HttpUtility.UrlDecode(manifestInfo["dipinstallpath"]);
+ if (!Directory.Exists(originGame.GameInstallDir))
{
- gamePath = manifestInfo["downloading"];
+ logger.Debug($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} found but no valid directory found at {originGame.GameInstallDir}");
+ continue;
}
}
+
+ // Now we want to look in the dinstallpath location for the game info
+ // for the __Installer\installerdata.xml
+
+ string gameInstallerData = Path.Combine(originGame.GameInstallDir, @"__Installer", @"installerdata.xml");
+
+ if (File.Exists(gameInstallerData))
+ {
+ // Now we parse the XML
+ XDocument xdoc = XDocument.Load(gameInstallerData);
+ originGame.GameName = xdoc.XPathSelectElement("/DiPManifest/gameTitles/gameTitle[@locale='en_US']").Value;
+ string gameFilePath = xdoc.XPathSelectElement("/DiPManifest/runtime/launcher/filePath").Value;
+ // Check whether gameFilePath contains a registry key! Cause if it does we need to lookup the path there instead
+ if (gameFilePath.StartsWith("[HKEY_LOCAL_MACHINE"))
+ {
+ // The filePath contains a registry key lookup that we need to execute and replace
+ MatchCollection mc = Regex.Matches(gameFilePath, @"\[HKEY_LOCAL_MACHINE\\(.*)\](.*)");
+ string originGameInstallKeyNameAndValue = mc[0].Groups[1].ToString();
+ string originGameRestOfFile = mc[0].Groups[2].ToString();
+ if (originGameInstallKeyNameAndValue == null)
+ {
+ // then we have a problem and we need to continue and ignore this game
+ logger.Warn($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} has registry but we can't match it! gameFilePath is {gameFilePath}.");
+ continue;
+ }
+
+ mc = Regex.Matches(originGameInstallKeyNameAndValue, @"(.*)\\([^\\]*)");
+ string originGameInstallKeyName = mc[0].Groups[1].ToString();
+ string originGameInstallKeyValue = mc[0].Groups[2].ToString();
+
+ try
+ {
+ RegistryKey originGameInstallKey = Registry.LocalMachine.OpenSubKey(originGameInstallKeyName, RegistryKeyPermissionCheck.ReadSubTree);
+ if (originGameInstallKey == null)
+ {
+ // then we have a problem as we cannot find the game exe location!
+ logger.Warn($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} has a install reg key we cannot find! originGameInstallKey is {gameFilePath} and originGameInstallKeyValue is {originGameInstallKeyValue}.");
+ continue;
+ }
+ string originGameInstallLocation = originGameInstallKey.GetValue(originGameInstallKeyValue).ToString();
+ originGameInstallLocation = Path.Combine(originGameInstallLocation, originGameRestOfFile);
+ if (!File.Exists(originGameInstallLocation))
+ {
+ // then we have a problem as we cannot locate the game exe file to start!
+ logger.Warn($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} has gameexe we cannot find! originGameInstallLocation is {originGameInstallLocation}.");
+ continue;
+ }
+ originGame.GameExePath = originGameInstallLocation;
+
+ }
+ catch (SecurityException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the permissions required to read the Origin Game location registry key {}.");
+ }
+ catch (ObjectDisposedException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The Microsoft.Win32.RegistryKey is closed when trying to access the Origin ClientPath registry key (closed keys cannot be accessed).");
+ }
+ catch (IOException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The Origin ClientPath registry key has been marked for deletion so we cannot access the value dueing the OriginLibrary check.");
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the necessary registry rights to check whether Origin is installed.");
+ }
+ }
+ else if (gameFilePath.StartsWith("[HKEY_CURRENT_USER"))
+ {
+ // The filePath contains a registry key lookup that we need to execute and replace
+ MatchCollection mc = Regex.Matches(gameFilePath, @"\[HKEY_CURRENT_USER\\(.*)\](.*)");
+ string originGameInstallKeyNameAndValue = mc[0].Groups[1].ToString();
+ string originGameRestOfFile = mc[0].Groups[2].ToString();
+ if (originGameInstallKeyNameAndValue == null)
+ {
+ // then we have a problem and we need to continue and ignore this game
+ logger.Warn($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} has registry but we can't match it! gameFilePath is {gameFilePath}.");
+ continue;
+ }
+
+ mc = Regex.Matches(originGameInstallKeyNameAndValue, @"(.*)\\([^\\]*)");
+ string originGameInstallKeyName = mc[0].Groups[1].ToString();
+ string originGameInstallKeyValue = mc[0].Groups[2].ToString();
+
+ try
+ {
+ RegistryKey originGameInstallKey = Registry.LocalMachine.OpenSubKey(originGameInstallKeyName, RegistryKeyPermissionCheck.ReadSubTree);
+ if (originGameInstallKey == null)
+ {
+ // then we have a problem as we cannot find the game exe location!
+ logger.Warn($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} has a install reg key we cannot find! originGameInstallKey is {gameFilePath} and originGameInstallKeyValue is {originGameInstallKeyValue}.");
+ continue;
+ }
+ string originGameInstallLocation = originGameInstallKey.GetValue(originGameInstallKeyValue).ToString();
+ originGameInstallLocation = Path.Combine(originGameInstallLocation, originGameRestOfFile);
+ if (!File.Exists(originGameInstallLocation))
+ {
+ // then we have a problem as we cannot locate the game exe file to start!
+ logger.Warn($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} has gameexe we cannot find! originGameInstallLocation is {originGameInstallLocation}.");
+ continue;
+ }
+ originGame.GameExePath = originGameInstallLocation;
+
+ }
+ catch (SecurityException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the permissions required to read the Origin Game location registry key {}.");
+ }
+ catch (ObjectDisposedException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The Microsoft.Win32.RegistryKey is closed when trying to access the Origin ClientPath registry key (closed keys cannot be accessed).");
+ }
+ catch (IOException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The Origin ClientPath registry key has been marked for deletion so we cannot access the value dueing the OriginLibrary check.");
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the necessary registry rights to check whether Origin is installed.");
+ }
+ }
+
+
+ if (!File.Exists(originGame.GameExePath))
+ {
+ logger.Debug($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} found but no game exe found at {originGame.GameExePath}");
+ continue;
+ }
+
+ // TODO check for icon! For now we will just use the exe one
+ originGame.GameOriginIconPath = originGame.GameExePath;
+
+ // If we reach here we add the Game to the list of games we have!
+ _allOriginGames.Add(new OriginGame(originGame.GameID, originGame.GameName, originGame.GameExePath, originGame.GameOriginIconPath));
+
+ }
+ else
+ {
+ // If we can't find the __Installer\installerdata.xml file then we ignore this game
+ continue;
+ }
+
+
+ }
+ catch (Exception ex)
+ {
+ logger.Error(ex, $"OriginLibrary/LoadInstalledGames: Failed to import installed Origin game {package}.");
+ }
+ }
+ }
+ else
+ {
+ logger.Warn($"OriginLibrary/LoadInstalledGames: No Origin games installed in the Origin library");
+ return false;
+ }
+
+ // up to here
+
+
+
+ /* if (gotGameRegistryKey)
+ {
+ // Now we need to lookup the game install path in registry using the game reg we got above
+ // We assume its 64-bit OS too (not 32bit)
+ using (RegistryKey OriginGameInstallKey = Registry.LocalMachine.OpenSubKey(gameRegistryKey, RegistryKeyPermissionCheck.ReadSubTree))
+ {
+ // If the key doesn't exist we skip it as the game isn't installed any longer!
+ if (OriginGameInstallKey == null)
+ {
+ logger.Trace($"OriginLibrary/LoadInstalledGames: Skipping Origin Game {OriginGameAppInfo.GameName} as it isn't installed at the moment (it was uninstalled at some point)");
+ continue;
+ }
+
+ // If we get here, then we have a real game.
+ foreach (string regKeyName in OriginGameInstallKey.GetValueNames())
+ {
+ logger.Trace($"OriginLibrary/LoadInstalledGames: OriginGameInstallKey[{regKeyName}] = {OriginGameInstallKey.GetValue(regKeyName)}");
+ }
+
+ // From that we lookup the actual game path
+ string gameInstallDir = OriginGameInstallKey.GetValue("InstallDir", "").ToString();
+ logger.Trace($"OriginLibrary/LoadInstalledGames: gameInstallDir found = {gameInstallDir}");
+ if (!String.IsNullOrWhiteSpace(gameInstallDir))
+ {
+ OriginGameAppInfo.GameInstallDir = Path.GetFullPath(gameInstallDir).TrimEnd('\\');
+ logger.Trace($"OriginLibrary/LoadInstalledGames: OriginGameAppInfo.GameInstallDir = {OriginGameAppInfo.GameInstallDir }");
+ OriginGameAppInfo.GameExe = Path.Combine(OriginGameAppInfo.GameInstallDir, gameFileName);
+ logger.Trace($"OriginLibrary/LoadInstalledGames: OriginGameAppInfo.GameExe = {OriginGameAppInfo.GameExePath }");
+ OriginGameAppInfo.GameID = gameId;
+ logger.Trace($"OriginLibrary/LoadInstalledGames: OriginGameAppInfo.GameID = {OriginGameAppInfo.GameID }");
+ }
+ else
+ {
+ logger.Warn($"OriginLibrary/LoadInstalledGames: gameInstallDir is null or all whitespace!");
+ }
+
+ // Then we have the gameID, the thumbimage, the icon, the name, the exe path
// And we add the Game to the list of games we have!
- _allOriginGames.Add(new OriginGame(gameId, gameName, gameExe, gameIconPath));
-
-
-
- var newGame = new GameInfo()
- {
- Source = "Origin",
- GameId = gameId,
- IsInstalled = true,
- Platform = "PC"
- };
-
- GameLocalDataResponse localData = null;
-
- try
- {
- localData = GetLocalManifest(gameId);
- }
- catch (Exception e) when (!Environment.IsDebugBuild)
- {
- logger.Error(e, $"Failed to get Origin manifest for a {gameId}, {package}");
- continue;
- }
-
- if (localData == null)
- {
- continue;
- }
-
- if (localData.offerType != "Base Game" && localData.offerType != "DEMO")
- {
- continue;
- }
-
- newGame.Name = StringExtensions.NormalizeGameName(localData.localizableAttributes.displayName);
- var installDir = GetInstallDirectory(localData);
- if (installDir.IsNullOrEmpty())
- {
- continue;
- }
-
- newGame.InstallDirectory = installDir;
- newGame.PlayAction = new GameAction
- {
- IsHandledByPlugin = true,
- Type = GameActionType.URL,
- Path = Origin.GetLaunchString(gameId)
- };
-
- games.Add(newGame.GameId, newGame);
- }
- catch (Exception e) when (!Environment.IsDebugBuild)
- {
- logger.Error(e, $"Failed to import installed Origin game {package}.");
+ _allOriginGames.Add(new OriginGame(OriginGameAppInfo.GameID, OriginGameAppInfo.GameName, OriginGameAppInfo.GameExePath, OriginGameAppInfo.GameOriginIconPath));
+ logger.Debug($"OriginLibrary/LoadInstalledGames: Adding Origin Game with game id {OriginGameAppInfo.GameID}, name {OriginGameAppInfo.GameName}, game exe {OriginGameAppInfo.GameExePath} and icon path {OriginGameAppInfo.GameOriginIconPath}");
}
}
+
+ }*/
+ logger.Info($"OriginLibrary/LoadInstalledGames: Found {_allOriginGames.Count} installed Origin games");
+ }
-
-
-
-
-
-
-
-
- List originAppIdsInstalled = new List();
- // Now look for what games app id's are actually installed on this computer
- using (RegistryKey originAppsKey = Registry.CurrentUser.OpenSubKey(_registryAppsKey, RegistryKeyPermissionCheck.ReadSubTree))
- {
- if (originAppsKey != null)
- {
- // Loop through the subKeys as they are the Origin Game IDs
- foreach (string originGameKeyName in originAppsKey.GetSubKeyNames())
- {
- if (int.TryParse(originGameKeyName, out int originAppId))
- {
- string originGameKeyFullName = $"{_registryAppsKey}\\{originGameKeyName}";
- using (RegistryKey originGameKey = Registry.CurrentUser.OpenSubKey(originGameKeyFullName, RegistryKeyPermissionCheck.ReadSubTree))
- {
- // If the Installed Value is set to 1, then the game is installed
- // We want to keep track of that for later
- if ((int)originGameKey.GetValue(@"Installed", 0) == 1)
- {
- // Add this Origin App ID to the list we're keeping for later
- originAppIdsInstalled.Add(originAppId);
- }
-
- }
-
- }
- }
- }
- }
-
- // Now we parse the origin appinfo.vdf to get access to things like:
- // - The game name
- // - THe game installation dir
- // - Sometimes the game icon
- // - Sometimes the game executable name (from which we can get the icon)
- Dictionary originAppInfo = new Dictionary();
-
- string appInfoVdfFile = Path.Combine(_originPath, "appcache", "appinfo.vdf");
- var newAppInfo = new AppInfo();
- newAppInfo.Read(appInfoVdfFile);
-
- Debug.WriteLine($"{newAppInfo.Apps.Count} apps");
-
- // Chec through all the apps we've extracted
- foreach (var app in newAppInfo.Apps)
- {
- // We only care about the appIDs we have listed as actual games
- // (The AppIds include all other DLC and Origin specific stuff too)
- int detectedAppID = Convert.ToInt32(app.AppID);
- if (originAppIdsInstalled.Contains(detectedAppID))
- {
-
- try
- {
-
- OriginAppInfo originGameAppInfo = new OriginAppInfo
- {
- GameID = detectedAppID,
- GameExes = new List()
- };
-
- foreach (KVObject data in app.Data)
- {
- //Debug.WriteLine($"App: {app.AppID} - Data.Name: {data.Name}");
-
- if (data.Name == "common")
- {
- foreach (KVObject common in data.Children)
- {
-
- //Debug.WriteLine($"App: {app.AppID} - Common {common.Name}: {common.Value}");
-
- if (common.Name == "name")
- {
- Debug.WriteLine($"App: {app.AppID} - Common {common.Name}: {common.Value}");
- originGameAppInfo.GameName = common.Value.ToString();
- }
- else if (common.Name == "clienticon")
- {
- Debug.WriteLine($"App: {app.AppID} - Common {common.Name}: {common.Value}");
- originGameAppInfo.GameOriginIconPath = Path.Combine(_originPath, @"origin", @"games", String.Concat(common.Value, @".ico"));
- }
- else if (common.Name == "type")
- {
- Debug.WriteLine($"App: {app.AppID} - Common {common.Name}: {common.Value}");
- }
- }
- }
- else if (data.Name == "config")
- {
- foreach (KVObject config in data.Children)
- {
- //Console.WriteLine($"App: {app.AppID} - Config {config.Name}: {config.Value}");
-
- if (config.Name == "installdir")
- {
- Debug.WriteLine($"App: {detectedAppID} - Config {config.Name}: {config.Value}");
- originGameAppInfo.GameInstallDir = config.Value.ToString();
- }
- else if (config.Name == "launch")
- {
- foreach (KVObject launch in config.Children)
- {
- foreach (KVObject launch_num in launch.Children)
- {
- if (launch_num.Name == "executable")
- {
- Debug.WriteLine($"App: {detectedAppID} - Config - Launch {launch.Name} - {launch_num.Name}: {launch_num.Value}");
- originGameAppInfo.GameExes.Add(launch_num.Value.ToString());
- }
-
- }
- }
- }
- }
- }
-
- }
- originAppInfo.Add(detectedAppID, originGameAppInfo);
- }
- catch (ArgumentException ex)
- {
- Console.WriteLine($"OriginGame/GetAllInstalledGames exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
- //we just want to ignore it if we try to add it twice....
- }
-
- Debug.WriteLine($"App: {detectedAppID} - Token: {app.Token}");
- }
- }
-
-
-
- // Now we access the config.vdf that lives in the Origin Config file, as that lists all
- // the OriginLibraries. We need to find out where they areso we can interrogate them
- _originConfigVdfFile = Path.Combine(_originPath, "config", "config.vdf");
- string originConfigVdfText = File.ReadAllText(_originConfigVdfFile, Encoding.UTF8);
-
- List originLibrariesPaths = new List();
- // Now we have to parse the config.vdf looking for the location of the OriginLibraries
- // We look for lines similar to this: "BaseInstallFolder_1" "E:\\OriginLibrary"
- // There may be multiple so we need to check the whole file
- Regex originLibrariesRegex = new Regex(@"""BaseInstallFolder_\d+""\s+""(.*)""", RegexOptions.IgnoreCase);
- // Try to match all lines against the Regex.
- MatchCollection originLibrariesMatches = originLibrariesRegex.Matches(originConfigVdfText);
- // If at least one of them matched!
- foreach (Match originLibraryMatch in originLibrariesMatches)
- {
- if (originLibraryMatch.Success)
- {
- string originLibraryPath = Regex.Unescape(originLibraryMatch.Groups[1].Value);
- Debug.WriteLine($"Found origin library: {originLibraryPath}");
- originLibrariesPaths.Add(originLibraryPath);
- }
- }
- // Now we go off and find the details for the games in each Origin Library
- foreach (string originLibraryPath in originLibrariesPaths)
- {
- // Work out the path to the appmanifests for this originLibrary
- string originLibraryAppManifestPath = Path.Combine(originLibraryPath, @"originapps");
- // Get the names of the App Manifests for the games installed in this OriginLibrary
- string[] originLibraryAppManifestFilenames = Directory.GetFiles(originLibraryAppManifestPath, "appmanifest_*.acf");
- // Go through each app and extract it's details
- foreach (string originLibraryAppManifestFilename in originLibraryAppManifestFilenames)
- {
- // Read in the contents of the file
- string originLibraryAppManifestText = File.ReadAllText(originLibraryAppManifestFilename);
- // Grab the appid from the file
- Regex appidRegex = new Regex(@"""appid""\s+""(\d+)""", RegexOptions.IgnoreCase);
- Match appidMatches = appidRegex.Match(originLibraryAppManifestText);
- if (appidMatches.Success)
- {
-
- if (int.TryParse(appidMatches.Groups[1].Value, out int originGameId))
- {
- // Check if this game is one that was installed
- if (originAppInfo.ContainsKey(originGameId))
- {
- // This game is an installed game! so we start to populate it with data!
- string originGameExe = "";
-
- string originGameName = originAppInfo[originGameId].GameName;
-
- // Construct the full path to the game dir from the appInfo and libraryAppManifest data
- string originGameInstallDir = Path.Combine(originLibraryPath, @"originapps", @"common", originAppInfo[originGameId].GameInstallDir);
-
- // And finally we try to populate the 'where', to see what gets run
- // And so we can extract the process name
- if (originAppInfo[originGameId].GameExes.Count > 0)
- {
- foreach (string gameExe in originAppInfo[originGameId].GameExes)
- {
- originGameExe = Path.Combine(originGameInstallDir, gameExe);
- // If the game executable exists, then we can proceed
- if (File.Exists(originGameExe))
- {
- break;
- }
- }
-
- }
-
- // Next, we need to get the Icons we want to use, and make sure it's the latest one.
- string originGameIconPath = "";
- // First of all, we attempt to use the Icon that Origin has cached, if it's available, as that will be updated to the latest
- if (File.Exists(originAppInfo[originGameId].GameOriginIconPath) && originAppInfo[originGameId].GameOriginIconPath.EndsWith(".ico"))
- {
- originGameIconPath = originAppInfo[originGameId].GameOriginIconPath;
- }
- // If there isn't an icon for us to use, then we need to extract one from the Game Executables
- else if (!String.IsNullOrEmpty(originGameExe))
- {
- originGameIconPath = originGameExe;
- }
- // The absolute worst case means we don't have an icon to use. SO we use the Origin one.
- else
- {
- // And we have to make do with a Origin Icon
- originGameIconPath = _originPath;
- }
-
- // And we add the Game to the list of games we have!
- _allOriginGames.Add(new OriginGame(originGameId, originGameName, originGameExe, originGameIconPath));
-
- }
- }
- }
- }
- }
+ catch (ArgumentNullException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/GetAllInstalledGames: An argument supplied to the function is null.");
+ }
+ catch (NotSupportedException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/GetAllInstalledGames: The invoked method is not supported or reading, seeking or writing tp a stream that isn't supported.");
+ }
+ catch (PathTooLongException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/GetAllInstalledGames: The path is longer than the maximum allowed by the operating system.");
}
catch (SecurityException ex)
{
- Console.WriteLine($"OriginGame/GetAllInstalledGames securityexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
- if (ex.Source != null)
- Console.WriteLine("SecurityException source: {0} - Message: {1}", ex.Source, ex.Message);
- throw;
- }
- catch (UnauthorizedAccessException ex)
- {
- Console.WriteLine($"OriginGame/GetAllInstalledGames unauthorizedaccessexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
- if (ex.Source != null)
- Console.WriteLine("UnauthorizedAccessException source: {0} - Message: {1}", ex.Source, ex.Message);
- throw;
+ logger.Warn(ex, "OriginLibrary/GetAllInstalledGames: The user does not have the permissions required to read the Origin InstallDir registry key.");
}
catch (ObjectDisposedException ex)
{
- Console.WriteLine($"OriginGame/GetAllInstalledGames objectdisposedexceptions: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
- if (ex.Source != null)
- Console.WriteLine("ObjectDisposedException source: {0} - Message: {1}", ex.Source, ex.Message);
- throw;
+ logger.Warn(ex, "OriginLibrary/GetAllInstalledGames: The Microsoft.Win32.RegistryKey is closed when trying to access the Origin InstallDir registry key (closed keys cannot be accessed).");
}
catch (IOException ex)
{
- Console.WriteLine($"OriginGame/GetAllInstalledGames ioexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
- // Extract some information from this exception, and then
- // throw it to the parent method.
- if (ex.Source != null)
- Console.WriteLine("IOException source: {0} - Message: {1}", ex.Source, ex.Message);
- throw;
+ logger.Warn(ex, "OriginLibrary/GetAllInstalledGames: The Origin InstallDir registry key has been marked for deletion so we cannot access the value dueing the OriginLibrary check.");
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ logger.Warn(ex, "OriginLibrary/GetAllInstalledGames: The user does not have the necessary registry rights to check whether Origin is installed.");
}
return true;
diff --git a/DisplayMagician/Program.cs b/DisplayMagician/Program.cs
index 08036b2..f1b3b2a 100644
--- a/DisplayMagician/Program.cs
+++ b/DisplayMagician/Program.cs
@@ -758,10 +758,36 @@ namespace DisplayMagician {
});
+ // Now lets prepare loading all the Origin games we have installed
+ Task loadOriginGamesTask = new Task(() =>
+ {
+ // Check if Origin is installed
+ if (GameLibraries.OriginLibrary.IsOriginInstalled)
+ {
+ // Load Origin library games
+ logger.Info($"Program/LoadGamesInBackground: Loading Installed Origin Games");
+ Console.Write("Loading Installed Origin Games...");
+ if (!DisplayMagician.GameLibraries.OriginLibrary.LoadInstalledGames())
+ {
+ logger.Info($"Program/LoadGamesInBackground: Cannot load installed Origin Games!");
+ }
+ Console.WriteLine("Done.");
+ logger.Info($"Program/LoadGamesInBackground: Loaded all Installed Origin Games (found {GameLibraries.OriginLibrary.InstalledOriginGameCount})");
+ }
+ else
+ {
+ logger.Info($"Program/LoadGamesInBackground: Origin not installed.");
+ Console.WriteLine("Origin not installed.");
+ }
+
+ });
+
+
// Store all the tasks in an array so we can wait on them later
- Task[] loadGamesTasks = new Task[2];
+ Task[] loadGamesTasks = new Task[3];
loadGamesTasks[0] = loadSteamGamesTask;
loadGamesTasks[1] = loadUplayGamesTask;
+ loadGamesTasks[2] = loadOriginGamesTask;
logger.Debug($"Program/LoadGamesInBackground: Running game loading tasks.");
// Go through and start all the tasks