Merged in hotfix for 1.0.6

This commit is contained in:
Terry MacDonald 2021-04-30 21:50:41 +12:00
commit 43374ff1b2
19 changed files with 623 additions and 410 deletions

View File

@ -40,6 +40,8 @@ namespace DisplayMagician.GameLibraries
public virtual bool IsRunning { get; set; }
public virtual bool IsUpdating { get; set; }
public virtual List<string> GameLibraryProcesses { get; set; }
#endregion

View File

@ -120,40 +120,13 @@ namespace DisplayMagician.GameLibraries
}
// Have to do much more research to figure out how to detect when Origin is updating a game
/*public override bool IsUpdating
public override bool IsUpdating
{
get
{
try
{
using (
var key = Registry.CurrentUser.OpenSubKey(_gameRegistryKey, RegistryKeyPermissionCheck.ReadSubTree))
{
if ((int)key?.GetValue(@"Updating", 0) == 1)
{
return true;
}
return false;
}
}
catch (SecurityException ex)
{
Console.WriteLine($"OriginGame/IsUpdating securityexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
if (ex.Source != null)
Console.WriteLine("SecurityException source: {0} - Message: {1}", ex.Source, ex.Message);
throw;
}
catch (IOException ex)
{
// Extract some information from this exception, and then
// throw it to the parent method.
Console.WriteLine($"OriginGame/IsUpdating ioexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
if (ex.Source != null)
Console.WriteLine("IOException source: {0} - Message: {1}", ex.Source, ex.Message);
throw;
}
}
}*/
public override GameStartMode StartMode
{

View File

@ -170,6 +170,18 @@ namespace DisplayMagician.GameLibraries
}
public override bool IsUpdating
{
get
{
// Not implemeted at present
// so we just return a false
// TODO Implement Origin specific detection for updating the game client
return false;
}
}
public override List<string> GameLibraryProcesses
{
get
@ -416,17 +428,21 @@ namespace DisplayMagician.GameLibraries
}
var localContentPath = Path.Combine(_originLocalContent, "LocalContent");
//var games = new Dictionary<string, GameInfo>();
logger.Trace($"OriginLibrary/LoadInstalledGames: Looking for Local Content in {localContentPath}");
if (Directory.Exists(localContentPath))
{
logger.Trace($"OriginLibrary/LoadInstalledGames: Local Content Directory {localContentPath} exists!");
string[] packages = Directory.GetFiles(localContentPath, "*.mfst", SearchOption.AllDirectories);
logger.Trace($"OriginLibrary/LoadInstalledGames: Found .mfst files in Local Content Directory {localContentPath}: {packages.ToString()}");
foreach (string package in packages)
{
logger.Trace($"OriginLibrary/LoadInstalledGames: Parsing {package} name to find GameID");
try
{
GameAppInfo originGame = new GameAppInfo();
originGame.GameID = Path.GetFileNameWithoutExtension(package);
logger.Trace($"OriginLibrary/LoadInstalledGames: Got GameID of {originGame.GameID } from file {package}");
if (!originGame.GameID.StartsWith("Origin"))
{
// If the gameId doesn't start with origin, then we need to find it!
@ -435,70 +451,101 @@ namespace DisplayMagician.GameLibraries
Match match = Regex.Match(originGame.GameID, @"^(.*?)(\d+)$");
if (!match.Success)
{
logger.Warn("Failed to get game id from file " + package);
logger.Warn($"OriginLibrary/LoadInstalledGames: Failed to match game id from file {package} name so ignoring game");
continue;
}
originGame.GameID = match.Groups[1].Value + ":" + match.Groups[2].Value;
logger.Trace($"OriginLibrary/LoadInstalledGames: GameID doesn't start with 'Origin' so using different pattern to find {originGame.GameID} GameID");
}
// Now we get the rest of the game information out of the manifest file
Dictionary<string, string> manifestInfo = ParseOriginManifest(package);
logger.Trace($"OriginLibrary/LoadInstalledGames: Looking whether Origin is still downloading the game to install it");
if (manifestInfo.ContainsKey("ddinitialdownload") && manifestInfo["ddinitialdownload"] == "1")
{
// Origin is downloading and installing the game so we skip it
logger.Warn($"OriginLibrary/LoadInstalledGames: Origin is still downloading the game with Game ID {originGame.GameID} to install it");
continue;
}
logger.Trace($"OriginLibrary/LoadInstalledGames: Looking whether Origin is downloading game updates");
if (manifestInfo.ContainsKey("downloading") && manifestInfo["downloading"] == "1")
{
// Origin is downloading some new content so we can't play it at the moment
// but we can still configure it
logger.Warn($"OriginLibrary/LoadInstalledGames: Origin is downloading game updates for the game with Game ID {originGame.GameID}");
continue;
}
originGame.GameInstallDir = null;
logger.Trace($"OriginLibrary/LoadInstalledGames: Looking where the game with Game ID {originGame.GameID} is installed");
if (manifestInfo.ContainsKey("dipinstallpath"))
{
// This is where Origin has installed this game
originGame.GameInstallDir = HttpUtility.UrlDecode(manifestInfo["dipinstallpath"]);
if (!Directory.Exists(originGame.GameInstallDir))
if (String.IsNullOrEmpty(originGame.GameInstallDir) || !Directory.Exists(originGame.GameInstallDir))
{
logger.Debug($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} found but no valid directory found at {originGame.GameInstallDir}");
logger.Warn($"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
else
{
logger.Warn($"OriginLibrary/LoadInstalledGames: Couldn't figure out where Game ID {originGame.GameID} is installed. Skipping game.");
}
string gameInstallerData = Path.Combine(originGame.GameInstallDir, @"__Installer", @"installerdata.xml");
logger.Trace($"OriginLibrary/LoadInstalledGames: Parsing the Game Installer Data at {gameInstallerData}");
if (File.Exists(gameInstallerData))
{
logger.Trace($"OriginLibrary/LoadInstalledGames: Game Installer Data file was found at {gameInstallerData}");
logger.Trace($"OriginLibrary/LoadInstalledGames: Attempting to parse XML Game Installer Data file at {gameInstallerData}");
// Now we parse the XML
XDocument xdoc = XDocument.Load(gameInstallerData);
originGame.GameName = xdoc.XPathSelectElement("/DiPManifest/gameTitles/gameTitle[@locale='en_US']").Value;
logger.Trace($"OriginLibrary/LoadInstalledGames: Game Name {originGame.GameName} found in Game Installer Data file {gameInstallerData}");
string gameFilePath = xdoc.XPathSelectElement("/DiPManifest/runtime/launcher/filePath").Value;
logger.Trace($"OriginLibrary/LoadInstalledGames: Game File Path is {gameFilePath } found in Game Installer Data file {gameInstallerData}");
string originGameInstallLocation = "";
// 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"))
{
logger.Trace($"OriginLibrary/LoadInstalledGames: Game File Path starts with a registery key so needs to be translated");
// The filePath contains a registry key lookup that we need to execute and replace
string originGameInstallKeyNameAndValue = "";
string originGameRestOfFile = "";
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)
if (mc.Count > 0)
{
// Split the Reg key bit from the File Path bit
originGameInstallKeyNameAndValue = mc[0].Groups[1].ToString();
logger.Trace($"OriginLibrary/LoadInstalledGames: originGameInstallKeyNameAndValue = {originGameInstallKeyNameAndValue}");
originGameRestOfFile = mc[0].Groups[2].ToString();
logger.Trace($"OriginLibrary/LoadInstalledGames: originGameRestOfFile = {originGameRestOfFile}");
if (originGameInstallKeyNameAndValue == null || originGameInstallKeyNameAndValue == "")
{
// 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}.");
logger.Warn($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} has registry key but we can't extract it! gameFilePath is {gameFilePath}.");
continue;
}
mc = Regex.Matches(originGameInstallKeyNameAndValue, @"(.*)\\([^\\]*)");
string originGameInstallKeyName = mc[0].Groups[1].ToString();
string originGameInstallKeyValue = mc[0].Groups[2].ToString();
// Split the reg key from the value name
string originGameInstallKeyName = "";
string originGameInstallKeyValue = "";
mc = Regex.Matches(originGameInstallKeyNameAndValue, @"(.*)\\([^\\]*)");
if (mc.Count > 0)
{
originGameInstallKeyName = mc[0].Groups[1].ToString();
logger.Trace($"OriginLibrary/LoadInstalledGames: originGameInstallKeyName = {originGameInstallKeyName }");
originGameInstallKeyValue = mc[0].Groups[2].ToString();
logger.Trace($"OriginLibrary/LoadInstalledGames: originGameInstallKeyValue = {originGameInstallKeyValue }");
}
// Lookup the reg key to figure out where the game is installed
try
{
RegistryKey originGameInstallKey = Registry.LocalMachine.OpenSubKey(originGameInstallKeyName, RegistryKeyPermissionCheck.ReadSubTree);
@ -508,8 +555,7 @@ namespace DisplayMagician.GameLibraries
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);
originGameInstallLocation = Path.Combine(originGameInstallKey.GetValue(originGameInstallKeyValue).ToString(), originGameRestOfFile);
if (!File.Exists(originGameInstallLocation))
{
// then we have a problem as we cannot locate the game exe file to start!
@ -517,29 +563,41 @@ namespace DisplayMagician.GameLibraries
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 {}.");
logger.Warn(ex, $"OriginLibrary/LoadInstalledGames: The user does not have the permissions required to read the Origin Game location registry key {originGameInstallKeyName}, so skipping game");
continue;
}
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).");
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), so skipping game");
continue;
}
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.");
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, so skipping game");
continue;
}
catch (UnauthorizedAccessException ex)
{
logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the necessary registry rights to check whether Origin is installed.");
logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the necessary registry rights to check whether Origin is installed, so skipping game");
continue;
}
}
else
{
logger.Warn($"OriginLibrary/LoadInstalledGames: Game File Path {gameFilePath} starts with '[HEKY_LOCAL_MACHINE' but didn't match the regex when it should have");
continue;
}
}
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\\(.*)\](.*)");
if (mc.Count > 0)
{
string originGameInstallKeyNameAndValue = mc[0].Groups[1].ToString();
string originGameRestOfFile = mc[0].Groups[2].ToString();
if (originGameInstallKeyNameAndValue == null)
@ -562,8 +620,7 @@ namespace DisplayMagician.GameLibraries
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);
originGameInstallLocation = Path.Combine(originGameInstallKey.GetValue(originGameInstallKeyValue).ToString(), originGameRestOfFile);
if (!File.Exists(originGameInstallLocation))
{
// then we have a problem as we cannot locate the game exe file to start!
@ -575,39 +632,56 @@ namespace DisplayMagician.GameLibraries
}
catch (SecurityException ex)
{
logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the permissions required to read the Origin Game location registry key {}.");
logger.Warn(ex, $"OriginLibrary/LoadInstalledGames: The user does not have the permissions required to read the Origin Game location registry key {originGameInstallKeyName}, so skipping game");
continue;
}
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).");
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), so skipping game");
continue;
}
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.");
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, so skipping game");
continue;
}
catch (UnauthorizedAccessException ex)
{
logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the necessary registry rights to check whether Origin is installed.");
logger.Warn(ex, "OriginLibrary/LoadInstalledGames: The user does not have the necessary registry rights to check whether Origin is installed, so skipping game");
continue;
}
}
else
{
logger.Warn($"OriginLibrary/LoadInstalledGames: Game File Path {gameFilePath} starts with '[HKEY_CURRENT_USER' but didn't match the regex when it should have, so skipping game");
continue;
}
}
else
{
// If we get here, then the gameFilepath is the actual filepath! So we just copy it.
logger.Trace($"OriginLibrary/LoadInstalledGames: Game File Path {gameFilePath} doesn't start with '[HKEY_LOCAL_MACHINE' or '[HKEY_CURRENT_USER' so it must be aplain file path");
originGame.GameExePath = gameFilePath;
}
if (!File.Exists(originGame.GameExePath))
{
logger.Debug($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} found but no game exe found at {originGame.GameExePath}");
logger.Warn($"OriginLibrary/LoadInstalledGames: Origin game with ID {originGame.GameID} found but no game exe found at originGame.GameExePath {originGame.GameExePath} so skipping game");
continue;
}
// TODO check for icon! For now we will just use the exe one
originGame.GameIconPath = originGame.GameExePath;
logger.Trace($"OriginLibrary/LoadInstalledGames: Origin gameIconPath = {originGame.GameIconPath} (currently just taking it from the file exe!");
// 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.GameIconPath));
}
else
{
// If we can't find the __Installer\installerdata.xml file then we ignore this game
logger.Trace($"OriginLibrary/LoadInstalledGames: Couldn't find Game Installer Data file at {gameInstallerData} for game with GameID {originGame.GameID} so skipping this game");
continue;
}
@ -625,55 +699,6 @@ namespace DisplayMagician.GameLibraries
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(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");
}

View File

@ -188,6 +188,18 @@ namespace DisplayMagician.GameLibraries
}
public override bool IsUpdating
{
get
{
// Not implemeted at present
// so we just return a false
// TODO Implement Origin specific detection for updating the game client
return false;
}
}
public override List<string> GameLibraryProcesses
{
get

View File

@ -120,40 +120,13 @@ namespace DisplayMagician.GameLibraries
}
// Have to do much more research to figure out how to detect when Uplay is updating a game
/*public override bool IsUpdating
public override bool IsUpdating
{
get
{
try
{
using (
var key = Registry.CurrentUser.OpenSubKey(_gameRegistryKey, RegistryKeyPermissionCheck.ReadSubTree))
{
if ((int)key?.GetValue(@"Updating", 0) == 1)
{
return true;
}
return false;
}
}
catch (SecurityException ex)
{
Console.WriteLine($"UplayGame/IsUpdating securityexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
if (ex.Source != null)
Console.WriteLine("SecurityException source: {0} - Message: {1}", ex.Source, ex.Message);
throw;
}
catch (IOException ex)
{
// Extract some information from this exception, and then
// throw it to the parent method.
Console.WriteLine($"UplayGame/IsUpdating ioexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
if (ex.Source != null)
Console.WriteLine("IOException source: {0} - Message: {1}", ex.Source, ex.Message);
throw;
}
}
}*/
public override GameStartMode StartMode
{

View File

@ -165,6 +165,18 @@ namespace DisplayMagician.GameLibraries
}
public override bool IsUpdating
{
get
{
// Not implemeted at present
// so we just return a false
// TODO Implement Uplay specific detection for updating the game client
return false;
}
}
public override List<string> GameLibraryProcesses
{
get
@ -547,6 +559,8 @@ namespace DisplayMagician.GameLibraries
if (uplayEntryLines[i].StartsWith(" name:", StringComparison.OrdinalIgnoreCase) && !gotGameName)
{
mc = Regex.Matches(uplayEntryLines[i], @" name\: (.*)");
if (mc.Count > 0)
{
uplayGameAppInfo.GameName = mc[0].Groups[1].ToString();
// if the name contains a localization reference, then dereference it
if (localizations.ContainsKey(uplayGameAppInfo.GameName))
@ -556,9 +570,12 @@ namespace DisplayMagician.GameLibraries
logger.Trace($"UplayLibrary/LoadInstalledGames: Found uplayGameAppInfo.GameName = {uplayGameAppInfo.GameName}");
gotGameName = true;
}
}
else if (uplayEntryLines[i].StartsWith(" icon_image:", StringComparison.OrdinalIgnoreCase) && !gotGameIconPath)
{
mc = Regex.Matches(uplayEntryLines[i], @"icon_image: (.*)");
if (mc.Count > 0)
{
string iconImageFileName = mc[0].Groups[1].ToString();
// if the icon_image contains a localization reference, then dereference it
if (localizations.ContainsKey(iconImageFileName))
@ -575,26 +592,39 @@ namespace DisplayMagician.GameLibraries
}
gotGameIconPath = true;
}
}
// This line contains the filename
else if (uplayEntryLines[i].StartsWith(" relative:") && !gotGameFileName)
{
mc = Regex.Matches(uplayEntryLines[i], @"relative: (.*)");
if (mc.Count > 0)
{
gameFileName = mc[0].Groups[1].ToString();
gotGameFileName = true;
logger.Trace($"UplayLibrary/LoadInstalledGames: Found gameFileName = {gameFileName}");
}
}
// This line contains the registryKey
else if (uplayEntryLines[i].StartsWith(" register: HKEY_LOCAL_MACHINE") && !gotGameId)
{
// Lookup the GameId within the registry key
mc = Regex.Matches(uplayEntryLines[i], @"Installs\\(\d+)\\InstallDir");
if (mc.Count > 0)
{
gameId = mc[0].Groups[1].ToString();
gotGameId = true;
logger.Trace($"UplayLibrary/LoadInstalledGames: Found gameId = {gameId}");
}
mc = Regex.Matches(uplayEntryLines[i], @"HKEY_LOCAL_MACHINE\\(.*?)\\InstallDir");
if (mc.Count > 0)
{
gameRegistryKey = mc[0].Groups[1].ToString();
gameRegistryKey = gameRegistryKey.Replace(@"Ubisoft", @"WOW6432Node\Ubisoft");
gotGameRegistryKey = true;
logger.Trace($"UplayLibrary/LoadInstalledGames: Found gameId = {gameId} and gameRegistryKey = {gameRegistryKey}");
logger.Trace($"UplayLibrary/LoadInstalledGames: Found gameRegistryKey = {gameRegistryKey}");
}
}
}

View File

@ -37,8 +37,8 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.5.0")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyVersion("1.0.6.0")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: NeutralResourcesLanguage("en")]
[assembly: CLSCompliant(true)]

View File

@ -150,7 +150,7 @@ namespace DisplayMagician
AutoSuggestShortcutName();
}
RefreshValidity();
//RefreshValidity();
}
@ -2077,66 +2077,55 @@ namespace DisplayMagician
}
else if (Category.Equals(ShortcutCategory.Game))
{
GameLibrary gameLibraryToUse = null;
// If the game is a Steam Game we check for that
if (GameLibrary.Equals(SupportedGameLibraryType.Steam))
{
// We now need to get the SteamGame info
gameLibraryToUse = SteamLibrary.GetLibrary();
}
// If the game is a Uplay Uplay Game we check for that
else if (GameLibrary.Equals(SupportedGameLibraryType.Uplay))
{
// We now need to get the Uplay Game info
gameLibraryToUse = UplayLibrary.GetLibrary();
}
// If the game is a Uplay Game we check for that
else if (GameLibrary.Equals(SupportedGameLibraryType.Origin))
{
// We now need to get the Uplay Game info
gameLibraryToUse = OriginLibrary.GetLibrary();
}
// If the game is a Steam Game we check for that
SteamLibrary steamLibrary = SteamLibrary.GetLibrary();
// First check if Steam is installed
// Check if Steam is installed and error if it isn't
if (!steamLibrary.IsGameLibraryInstalled)
if (!gameLibraryToUse.IsGameLibraryInstalled)
{
ShortcutError error = new ShortcutError();
error.Name = "SteamNotInstalled";
error.Name = $"{gameLibraryToUse.GameLibraryName}NotInstalled";
error.Validity = ShortcutValidity.Error;
error.Message = $"Steam is not installed on this computer.";
error.Message = $"{gameLibraryToUse.GameLibraryName} is not installed on this computer.";
_shortcutErrors.Add(error);
if (worstError != ShortcutValidity.Error)
worstError = ShortcutValidity.Error;
}
// We need to look up details about the game
if (!steamLibrary.ContainsGameById(GameAppId))
if (!gameLibraryToUse.ContainsGameById(GameAppId))
{
ShortcutError error = new ShortcutError();
error.Name = "SteamGameNotInstalled";
error.Name = "{gameLibraryToUse.GameLibraryName}GameNotInstalled";
error.Validity = ShortcutValidity.Error;
error.Message = $"The Steam Game with AppID '{GameAppId}' is not installed on this computer.";
error.Message = $"The {gameLibraryToUse.GameLibraryName} Game with AppID '{GameAppId}' is not installed on this computer.";
_shortcutErrors.Add(error);
if (worstError != ShortcutValidity.Error)
worstError = ShortcutValidity.Error;
}
}
// If the game is a Uplay Game we check for that
else if (GameLibrary.Equals(SupportedGameLibraryType.Uplay))
{
UplayLibrary uplayLibrary = UplayLibrary.GetLibrary();
// First check if Uplay is installed
// Check if Uplay is installed and error if it isn't
if (!uplayLibrary.IsGameLibraryInstalled)
{
ShortcutError error = new ShortcutError();
error.Name = "UplayNotInstalled";
error.Validity = ShortcutValidity.Error;
error.Message = $"Uplay is not installed on this computer.";
_shortcutErrors.Add(error);
if (worstError != ShortcutValidity.Error)
worstError = ShortcutValidity.Error;
}
// We need to look up details about the game
if (!uplayLibrary.ContainsGame(GameAppId))
{
ShortcutError error = new ShortcutError();
error.Name = "UplayGameNotInstalled";
error.Validity = ShortcutValidity.Error;
error.Message = $"The Uplay Game with AppID '{GameAppId}' is not installed on this computer.";
_shortcutErrors.Add(error);
if (worstError != ShortcutValidity.Error)
worstError = ShortcutValidity.Error;
}
}
}
// Check the Audio Device is still valid (if one is specified)
CoreAudioController audioController = ShortcutRepository.AudioController;
if (ChangeAudioDevice)

View File

@ -1023,8 +1023,7 @@ namespace DisplayMagician
Thread.Sleep(1000);
}
}
logger.Debug($"ShortcutRepository/RunShortcut: Executable {processNameToLookFor} has exited.");
logger.Info($"ShortcutRepository/RunShortcut: Executable {processNameToLookFor} has exited.");
logger.Debug($"ShortcutRepository/RunShortcut: Creating a Windows Toast to notify the user that the executable {shortcutToUse.ExecutableNameAndPath} has closed.");
// Tell the user that the application has closed
@ -1063,11 +1062,11 @@ namespace DisplayMagician
// We now need to get the Uplay Game info
gameLibraryToUse = UplayLibrary.GetLibrary();
}
// If the game is a Uplay Game we check for that
// If the game is an Origin Game we check for that
else if (shortcutToUse.GameLibrary.Equals(SupportedGameLibraryType.Origin))
{
// We now need to get the Uplay Game info
gameLibraryToUse = UplayLibrary.GetLibrary();
// We now need to get the Origin Game info
gameLibraryToUse = OriginLibrary.GetLibrary();
}
gameToRun = gameLibraryToUse.GetGameById(shortcutToUse.GameAppId);
@ -1119,7 +1118,7 @@ namespace DisplayMagician
Thread.Sleep(500);
// Wait for GameLibrary to start
for (int secs = 0; secs >= (shortcutToUse.StartTimeout * 1000); secs += 500)
for (int secs = 0; secs <= (shortcutToUse.StartTimeout * 1000); secs += 500)
{
// If we have found one or more processes then we should be good to go
@ -1136,14 +1135,96 @@ namespace DisplayMagician
}
// Check whether GameLibrary is updating (if it supports finding that out!)
// Note - this is the scaffolding in place for the future. It will allow future ability to
// detect game library updates if I can find a way of developing them per library in the future.
if (gameLibraryToUse.IsUpdating)
{
logger.Info($"ShortcutRepository/RunShortcut: GameLibrary {gameLibraryToUse.GameLibraryName} has started updating itself.");
// Now we want to tell the user we're updating the game library
// Construct the Windows toast content
tcBuilder = new ToastContentBuilder()
.AddToastActivationInfo($"notify=updating{gameLibraryToUse.GameLibraryName}", ToastActivationType.Foreground)
.AddText($"Updating {gameLibraryToUse.GameLibraryName}", hintMaxLines: 1)
.AddText($"Waiting for {gameLibraryToUse.GameLibraryName} Game Library to update itself...");
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
toastContent = tcBuilder.Content;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
// And create the toast notification
toast = new ToastNotification(doc);
// Remove any other Notifications from us
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show this notification
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
// Wait for up to 5 minutes for GameLibrary to update
for (int secs = 0; secs <= 5000; secs += 500)
{
// If the game library has finished updating then let's break, and get to the next step....
if (!gameLibraryToUse.IsUpdating)
{
logger.Info($"ShortcutRepository/RunShortcut: GameLibrary {gameLibraryToUse.GameLibraryName} has finished updating.");
break;
}
// Let's wait a little while while the GameLibrary is updating
Thread.Sleep(500);
}
}
// Delay 5secs
Thread.Sleep(5000);
logger.Debug($"ShortcutRepository/RunShortcut: Pausing to let the game library start the game.");
Thread.Sleep(5000);
// Store the Process ID for later
//IPCService.GetInstance().HoldProcessId = gameLibraryProcesses.FirstOrDefault()?.Id ?? 0;
//IPCService.GetInstance().Status = InstanceStatus.OnHold;
// Check whether Game itself is updating (if it supports finding that out!)
// Note - this is the scaffolding in place for the future. It will allow future ability to
// detect game library updates if I can find a way of developing them per library in the future.
if (gameToRun.IsUpdating)
{
logger.Info($"ShortcutRepository/RunShortcut: Game {gameToRun.Name} is being updated so we'll wait up to 15 mins until it's finished.");
// Now we want to tell the user we're updating the game
// Construct the Windows toast content
tcBuilder = new ToastContentBuilder()
.AddToastActivationInfo($"notify=updating{gameToRun.Name}", ToastActivationType.Foreground)
.AddText($"Updating {gameToRun.Name}", hintMaxLines: 1)
.AddText($"Waiting for {gameToRun.Name} Game to update...");
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
toastContent = tcBuilder.Content;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
// And create the toast notification
toast = new ToastNotification(doc);
// Remove any other Notifications from us
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show this notification
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
// Wait for up to 15 minutes for the Game to update
for (int secs = 0; secs <= 15000; secs += 500)
{
// If the game library has finished updating then let's break, and get to the next step....
if (!gameToRun.IsUpdating)
{
logger.Info($"ShortcutRepository/RunShortcut: Game {gameToRun.Name} has finished updating.");
break;
}
// Let's wait a little while while the GameLibrary is updating
Thread.Sleep(500);
}
}
// At this point, if the user wants to actually monitor a different process,
// then we actually need to monitor that instead
if (shortcutToUse.MonitorDifferentGameExe)
@ -1158,24 +1239,6 @@ namespace DisplayMagician
notifyIcon.Text = $"DisplayMagician: Running {gameToRun.Name.Substring(0, 41)}...";
Application.DoEvents();
// Now we want to tell the user we're running a game!
// Construct the Windows toast content
tcBuilder = new ToastContentBuilder()
.AddToastActivationInfo($"notify=running{gameLibraryToUse.GameLibraryName}Game", ToastActivationType.Foreground)
.AddText($"Running {shortcutToUse.GameName}", hintMaxLines: 1)
.AddText($"Waiting for the {altGameProcessToMonitor} alternative game process to exit...");
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
toastContent = tcBuilder.Content;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
// And create the toast notification
toast = new ToastNotification(doc);
// Remove any other Notifications from us
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show this notification
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
// Now look for the thing we're supposed to monitor
// and wait until it starts up
List<Process> processesToMonitor = new List<Process>();
@ -1196,17 +1259,137 @@ namespace DisplayMagician
// any processes yet
Thread.Sleep(500);
}
// make sure we have things to monitor and alert if not
// make sure we have an alternative game executable to monitor
if (processesToMonitor.Count == 0)
{
logger.Error($"ShortcutRepository/RunShortcut: No Alternative Game Executable '{altGameProcessToMonitor}' processes found before waiting timeout. DisplayMagician was unable to find any processes before the {shortcutToUse.StartTimeout} second timeout");
// if we didn't find an alternative game exectuable to monitor, then we need to go for the game executable itself as a fall back
logger.Error($"ShortcutRepository/RunShortcut: No Alternative Game Executable '{altGameProcessToMonitor}' processes found before waiting timeout. DisplayMagician was unable to find any alternative processes before the {shortcutToUse.StartTimeout} second timeout");
logger.Info($"ShortcutRepository/RunShortcut: Ignoring monitoring Alternative Game Executable '{altGameProcessToMonitor}' processes. Reverting back to monitoring Game executables '{gameToRun.ProcessName}' instead.");
// we wait until the game has started running (*allows for updates to occur)
for (int secs = 0; secs <= (shortcutToUse.StartTimeout * 1000); secs += 500)
{
if (gameToRun.IsRunning)
{
// The game is running! So now we continue processing
logger.Debug($"ShortcutRepository/RunShortcut: Found the '{gameToRun.Name}' process has started");
break;
}
// if we have things to monitor, then we should start to wait for them
logger.Debug($"ShortcutRepository/RunShortcut: Waiting for alternative game proocess {altGameProcessToMonitor} to exit.");
if (processesToMonitor.Count > 0)
// Delay 500ms
Thread.Sleep(500);
}
// If the game still isn't running then there is an issue so tell the user and revert things back
if (!gameToRun.IsRunning)
{
logger.Error($"ShortcutRepository/RunShortcut: The Game {gameToRun.Name} didn't start for some reason (or the game uses a starter exe that launches the game itself)! so reverting changes back if needed...");
logger.Warn($"ShortcutRepository/RunShortcut: We were monitoring {gameToRun.ExePath}. You may need to manually add an alternative game executable to monitor - please run the game manually and check if another executable in {Path.GetDirectoryName(gameToRun.ExePath)} is run, and then monitor that instead.");
// Now we want to tell the user we couldn't start the game!
// Construct the Windows toast content
tcBuilder = new ToastContentBuilder()
.AddToastActivationInfo($"notify=errorRunning{gameLibraryToUse.GameLibraryName}Game", ToastActivationType.Foreground)
.AddText($"Could not detect {shortcutToUse.GameName} starting", hintMaxLines: 1)
.AddText($"Could not detect {shortcutToUse.GameName} Game starting, so reverting changes back if needed. You may need to monitor a different game executable.");
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
toastContent = tcBuilder.Content;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
// And create the toast notification
toast = new ToastNotification(doc);
// Remove any other Notifications from us
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show this notification
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
}
else
{
// The game has started correctly so we continue to monitor it!
// Tell the user
// Now we want to tell the user we're running a game!
// Construct the Windows toast content
tcBuilder = new ToastContentBuilder()
.AddToastActivationInfo($"notify=running{gameLibraryToUse.GameLibraryName}Game", ToastActivationType.Foreground)
.AddText($"Running {shortcutToUse.GameName}", hintMaxLines: 1)
.AddText($"Waiting for the {gameToRun.ProcessName} game process to exit as {altGameProcessToMonitor} alternative game executable wasn't found...");
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
toastContent = tcBuilder.Content;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
// And create the toast notification
toast = new ToastNotification(doc);
// Remove any other Notifications from us
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show this notification
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
// This is the main waiting thread!
// Wait for the game to exit
logger.Debug($"ShortcutRepository/RunShortcut: waiting for {gameLibraryToUse.GameLibraryName} Game {gameToRun.Name} to exit.");
while (true)
{
if (!gameToRun.IsRunning)
{
logger.Debug($"ShortcutRepository/RunShortcut: {gameLibraryToUse.GameLibraryName} Game {gameToRun.Name} is no longer running (IsRunning is false).");
break;
}
// Send a message to windows so that it doesn't think
// we're locked and try to kill us
System.Threading.Thread.CurrentThread.Join(0);
Thread.Sleep(1000);
}
logger.Debug($"ShortcutRepository/RunShortcut: {gameLibraryToUse.GameLibraryName} Game {gameToRun.Name} has exited.");
// Tell the user that the Game has closed
// Construct the toast content
tcBuilder = new ToastContentBuilder()
.AddToastActivationInfo("notify=stopDetected", ToastActivationType.Foreground)
.AddText($"{shortcutToUse.GameName} was closed", hintMaxLines: 1)
.AddText($"{shortcutToUse.GameName} game was exited.");
toastContent = tcBuilder.Content;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
// And create the toast notification
toast = new ToastNotification(doc);
// Remove any other Notifications from us
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show it
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
}
}
else
{
// we found alternative game executable processes, so we'll just monitor them
logger.Debug($"ShortcutRepository/RunShortcut: Waiting for alternative game proocess {altGameProcessToMonitor} to exit.");
logger.Debug($"ShortcutRepository/RunShortcut: {processesToMonitor.Count} Alternative Game Executable '{altGameProcessToMonitor}' processes are still running");
// Now we want to tell the user we're monitoring the alternative executables!
// Construct the Windows toast content
tcBuilder = new ToastContentBuilder()
.AddToastActivationInfo($"notify=running{gameLibraryToUse.GameLibraryName}Game", ToastActivationType.Foreground)
.AddText($"Running {shortcutToUse.GameName}", hintMaxLines: 1)
.AddText($"Waiting for the {altGameProcessToMonitor} alternative game process to exit...");
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
toastContent = tcBuilder.Content;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
// And create the toast notification
toast = new ToastNotification(doc);
// Remove any other Notifications from us
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show this notification
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
while (true)
{
processesToMonitor = Process.GetProcessesByName(altGameProcessToMonitor).ToList();
@ -1223,9 +1406,7 @@ namespace DisplayMagician
System.Threading.Thread.CurrentThread.Join(0);
Thread.Sleep(1000);
}
}
logger.Debug($"ShortcutRepository/RunShortcut: Alternative Game Executable {altGameProcessToMonitor} has exited.");
// Tell the user that the Alt Game Executable has closed
// Construct the toast content
tcBuilder = new ToastContentBuilder()
@ -1242,7 +1423,7 @@ namespace DisplayMagician
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show it
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
}
}
else
{
@ -1276,7 +1457,7 @@ namespace DisplayMagician
// Now we know the game library app is running then
// we wait until the game has started running (*allows for updates to occur)
for (int secs = 0; secs >= (shortcutToUse.StartTimeout * 1000); secs += 500)
for (int secs = 0; secs <= (shortcutToUse.StartTimeout * 1000); secs += 500)
{
if (gameToRun.IsRunning)
@ -1291,9 +1472,32 @@ namespace DisplayMagician
}
// Wait 5 more seconds for the game process to spawn
// Thread.Sleep(5000);
// If the game still isn't running then there is an issue so tell the user and revert things back
if (!gameToRun.IsRunning)
{
logger.Error($"ShortcutRepository/RunShortcut: The Game {gameToRun.Name} didn't start for some reason (or the game uses a starter exe that launches the game itself)! so reverting changes back if needed...");
logger.Warn($"ShortcutRepository/RunShortcut: We were monitoring {gameToRun.ExePath}. You may need to manually add an alternative game executable to monitor - please run the game manually and check if another executable in {Path.GetDirectoryName(gameToRun.ExePath)} is run, and then monitor that instead.");
// Now we want to tell the user we couldn't start the game!
// Construct the Windows toast content
tcBuilder = new ToastContentBuilder()
.AddToastActivationInfo($"notify=errorRunning{gameLibraryToUse.GameLibraryName}Game", ToastActivationType.Foreground)
.AddText($"Could not detect {shortcutToUse.GameName} starting", hintMaxLines: 1)
.AddText($"Could not detect {shortcutToUse.GameName} Game starting, so reverting changes back if needed. You may need to monitor a different game executable.");
//.AddButton("Stop", ToastActivationType.Background, "notify=runningGame&action=stop");
toastContent = tcBuilder.Content;
// Make sure to use Windows.Data.Xml.Dom
doc = new XmlDocument();
doc.LoadXml(toastContent.GetContent());
// And create the toast notification
toast = new ToastNotification(doc);
// Remove any other Notifications from us
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show this notification
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
}
else
{
// This is the main waiting thread!
// Wait for the game to exit
logger.Debug($"ShortcutRepository/RunShortcut: waiting for {gameLibraryToUse.GameLibraryName} Game {gameToRun.Name} to exit.");
@ -1310,7 +1514,6 @@ namespace DisplayMagician
System.Threading.Thread.CurrentThread.Join(0);
Thread.Sleep(1000);
}
Console.WriteLine($"{gameToRun.Name} has exited.");
logger.Debug($"ShortcutRepository/RunShortcut: {gameLibraryToUse.GameLibraryName} Game {gameToRun.Name} has exited.");
// Tell the user that the Game has closed
@ -1329,15 +1532,14 @@ namespace DisplayMagician
DesktopNotifications.DesktopNotificationManagerCompat.History.Clear();
// And then show it
DesktopNotifications.DesktopNotificationManagerCompat.CreateToastNotifier().Show(toast);
}
}
}
else
{
logger.Error($"ShortcutRepository/RunShortcut: Error starting the {gameToRun.Name} {gameToRun.GameLibrary} Game as the game wasn't found.");
}
}

View File

@ -87,12 +87,12 @@
<Version>4.0.0-alpha5</Version>
</PackageReference>
<PackageReference Include="Costura.Fody">
<Version>5.0.2</Version>
<Version>5.3.0</Version>
<IncludeAssets>compile; runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Fody">
<Version>6.4.0</Version>
<Version>6.5.1</Version>
<!-- <IncludeAssets>compile; runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> -->
<PrivateAssets>all</PrivateAssets>
</PackageReference>

View File

@ -19,12 +19,12 @@
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of (.NET Core) runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of (.NET Core) runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
@ -55,7 +55,12 @@
</xs:attribute>
<xs:attribute name="IncludeRuntimeReferences" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if (.NET Core) runtime assemblies are also embedded.</xs:documentation>
<xs:documentation>Controls if runtime assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseRuntimeReferencePaths" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCompression" type="xs:boolean">
@ -90,12 +95,12 @@
</xs:attribute>
<xs:attribute name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of (.NET Core) runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of (.NET Core) runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">

View File

@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.5.0")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyVersion("1.0.6.0")]
[assembly: AssemblyFileVersion("1.0.6.0")]

View File

@ -31,6 +31,7 @@
<Pedantic>True</Pedantic>
<WixVariables>
</WixVariables>
<SuppressPdbOutput>True</SuppressPdbOutput>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<OutputPath>bin\$(Platform)\$(Configuration)\</OutputPath>
@ -38,6 +39,7 @@
<SuppressAllWarnings>False</SuppressAllWarnings>
<Pedantic>True</Pedantic>
<DefineConstants>DisplayMagicianFilesDir=H:\vscode-projects\DisplayMagician\DisplayMagician\bin\Debug</DefineConstants>
<SuppressPdbOutput>True</SuppressPdbOutput>
</PropertyGroup>
<ItemGroup>
<Compile Include="CustomDialogs\LicenseAgreementDialogOverwritten.wxs" />

View File

@ -6,10 +6,10 @@
-->
<?define MajorVersion="1" ?>
<?define MinorVersion="0" ?>
<?define BuildVersion="5" ?>
<?define PatchVersion="6" ?>
<!-- Revision is NOT used by WiX in the upgrade procedure -->
<!-- Full version number to display -->
<?define VersionNumber="$(var.MajorVersion).$(var.MinorVersion).$(var.BuildVersion)" ?>
<?define VersionNumber="$(var.MajorVersion).$(var.MinorVersion).$(var.PatchVersion)" ?>
<!--
Upgrade code HAS to be the same for all updates.

View File

@ -116,7 +116,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>12.0.3</Version>
<Version>13.0.1</Version>
</PackageReference>
<PackageReference Include="NHotkey">
<Version>2.1.0</Version>
@ -125,7 +125,7 @@
<Version>2.1.0</Version>
</PackageReference>
<PackageReference Include="NLog">
<Version>4.7.8</Version>
<Version>4.7.9</Version>
</PackageReference>
<PackageReference Include="NvAPIWrapper.Net">
<Version>0.8.1.101</Version>

View File

@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.5.0")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyVersion("1.0.6.0")]
[assembly: AssemblyFileVersion("1.0.6.0")]

View File

@ -35,5 +35,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.5.0")]
[assembly: AssemblyFileVersion("1.0.5.0")]
[assembly: AssemblyVersion("1.0.6.0")]
[assembly: AssemblyFileVersion("1.0.6.0")]

View File

@ -13,10 +13,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="nunit" Version="3.13.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="nunit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
</ItemGroup>
<ItemGroup>

View File

@ -1,6 +1,6 @@
{
"version": "1.0.5.0",
"url": "https://github.com/terrymacdonald/DisplayMagician/releases/download/v1.0.5/DisplayMagicianSetup-v1.0.5.msi",
"version": "1.0.6.0",
"url": "https://github.com/terrymacdonald/DisplayMagician/releases/download/v1.0.6/DisplayMagicianSetup-v1.0.6.msi",
"changelog": "https://github.com/terrymacdonald/DisplayMagician/releases",
"mandatory": {
"value": false,
@ -8,7 +8,7 @@
"mode": 0
},
"checksum": {
"value": "36273CAEB4E7FE006ED48400CC243B0D01CE4AEFCF8F399A9641B7C124245F79",
"value": "078DAE73B1648410F7AB9E21392B7C55A9EA8C1980AC468B2AC2951F3E49853E",
"hashingAlgorithm": "SHA256"
}
}