mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
Fixed Steam and Uplay game detection
Fixed an issue where Steam and Uplay don't detect the game correctly. Now they find the processes themselves. Also fixed ProgramSettings so that it generates a new settings file on startup. Also added LogLevel option to the ProgramSettings so that I can start rolling out the NLog log statements to report errors from the binary when it's installed on people's PCs.
This commit is contained in:
parent
c0389cdba7
commit
0830ed58dd
@ -3,39 +3,15 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Drawing;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using DisplayMagician.Resources;
|
||||
using DisplayMagician.Shared;
|
||||
//using HtmlAgilityPack;
|
||||
using Microsoft.Win32;
|
||||
using Newtonsoft.Json;
|
||||
//using VdfParser;
|
||||
//using Gameloop.Vdf;
|
||||
using System.Collections.ObjectModel;
|
||||
using ValveKeyValue;
|
||||
using System.Security.Cryptography;
|
||||
using System.ServiceModel.Configuration;
|
||||
using DisplayMagician.GameLibraries.SteamAppInfoParser;
|
||||
using TsudaKageyu;
|
||||
using System.Drawing.IconLib;
|
||||
using System.Drawing.IconLib.Exceptions;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace DisplayMagician.GameLibraries
|
||||
{
|
||||
public class SteamGame : Game
|
||||
{
|
||||
/*private static string SteamLibrary.SteamExe;
|
||||
private static string SteamLibrary.SteamPath;
|
||||
private static string _steamConfigVdfFile;
|
||||
private static string _registrySteamKey = @"SOFTWARE\\Valve\\Steam";
|
||||
private static string _registryAppsKey = $@"{_registrySteamKey}\\Apps";*/
|
||||
private string _gameRegistryKey;
|
||||
private uint _steamGameId;
|
||||
private string _steamGameName;
|
||||
@ -46,15 +22,6 @@ namespace DisplayMagician.GameLibraries
|
||||
private string _steamGameIconPath;
|
||||
private static List<SteamGame> _allInstalledSteamGames = null;
|
||||
|
||||
/*private struct SteamAppInfo
|
||||
{
|
||||
public uint GameID;
|
||||
public string GameName;
|
||||
public List<string> GameExes;
|
||||
public string GameInstallDir;
|
||||
public string GameSteamIconPath;
|
||||
}*/
|
||||
|
||||
static SteamGame()
|
||||
{
|
||||
ServicePointManager.ServerCertificateValidationCallback +=
|
||||
@ -104,49 +71,27 @@ namespace DisplayMagician.GameLibraries
|
||||
|
||||
public override string Directory
|
||||
{
|
||||
get => _steamGameExePath;
|
||||
set => _steamGameExePath = value;
|
||||
get => _steamGameDir;
|
||||
set => _steamGameDir = value;
|
||||
}
|
||||
|
||||
public override bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
/*try
|
||||
{
|
||||
using (
|
||||
var key = Registry.CurrentUser.OpenSubKey(_gameRegistryKey, RegistryKeyPermissionCheck.ReadSubTree))
|
||||
{
|
||||
if ((int)key?.GetValue(@"Running", 0) == 1)
|
||||
int numGameProcesses = 0;
|
||||
List<Process> gameProcesses = Process.GetProcessesByName(_steamGameProcessName).ToList();
|
||||
foreach (Process gameProcess in gameProcesses)
|
||||
{
|
||||
if (gameProcess.MainModule.FileName.StartsWith(_steamGameExePath))
|
||||
numGameProcesses++;
|
||||
}
|
||||
if (numGameProcesses > 0)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (SecurityException ex)
|
||||
{
|
||||
Console.WriteLine($"SteamGame/IsRunning 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($"SteamGame/IsRunning ioexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
||||
if (ex.Source != null)
|
||||
Console.WriteLine("IOException source: {0} - Message: {1}", ex.Source, ex.Message);
|
||||
throw;
|
||||
}*/
|
||||
|
||||
bool isRunning = Process.GetProcessesByName(_steamGameProcessName)
|
||||
.FirstOrDefault(p => p.MainModule.FileName
|
||||
.StartsWith(ExePath,StringComparison.OrdinalIgnoreCase)) != default(Process);
|
||||
return isRunning;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsUpdating
|
||||
{
|
||||
@ -193,6 +138,7 @@ namespace DisplayMagician.GameLibraries
|
||||
steamGame.Id = Id;
|
||||
steamGame.Name = Name;
|
||||
steamGame.ExePath = ExePath;
|
||||
steamGame.Directory = Directory;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -107,49 +107,27 @@ namespace DisplayMagician.GameLibraries
|
||||
|
||||
public override string Directory
|
||||
{
|
||||
get => _uplayGameExePath;
|
||||
set => _uplayGameExePath = value;
|
||||
get => _uplayGameDir;
|
||||
set => _uplayGameDir = value;
|
||||
}
|
||||
|
||||
public override bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
/*try
|
||||
{
|
||||
using (
|
||||
var key = Registry.CurrentUser.OpenSubKey(_gameRegistryKey, RegistryKeyPermissionCheck.ReadSubTree))
|
||||
{
|
||||
if ((int)key?.GetValue(@"Running", 0) == 1)
|
||||
int numGameProcesses = 0;
|
||||
List<Process> gameProcesses = Process.GetProcessesByName(_uplayGameProcessName).ToList();
|
||||
foreach (Process gameProcess in gameProcesses)
|
||||
{
|
||||
if (gameProcess.MainModule.FileName.StartsWith(_uplayGameExePath))
|
||||
numGameProcesses++;
|
||||
}
|
||||
if (numGameProcesses > 0)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (SecurityException ex)
|
||||
{
|
||||
Console.WriteLine($"UplayGame/IsRunning 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/IsRunning ioexception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
||||
if (ex.Source != null)
|
||||
Console.WriteLine("IOException source: {0} - Message: {1}", ex.Source, ex.Message);
|
||||
throw;
|
||||
}*/
|
||||
|
||||
bool isRunning = Process.GetProcessesByName(_uplayGameProcessName)
|
||||
.FirstOrDefault(p => p.MainModule.FileName
|
||||
.StartsWith(ExePath, StringComparison.OrdinalIgnoreCase)) != default(Process);
|
||||
return isRunning;
|
||||
}
|
||||
}
|
||||
|
||||
/*public override bool IsUpdating
|
||||
{
|
||||
@ -196,6 +174,7 @@ namespace DisplayMagician.GameLibraries
|
||||
uplayGame.Id = Id;
|
||||
uplayGame.Name = Name;
|
||||
uplayGame.ExePath = ExePath;
|
||||
uplayGame.Directory = Directory;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,25 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using McMaster.Extensions.CommandLineUtils;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using DisplayMagician.InterProcess;
|
||||
using DisplayMagician.Resources;
|
||||
using DisplayMagician.GameLibraries;
|
||||
using DisplayMagician.Shared;
|
||||
using DisplayMagician.UIForms;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Drawing;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace DisplayMagician {
|
||||
|
||||
@ -60,7 +53,7 @@ namespace DisplayMagician {
|
||||
|
||||
// Targets where to log to: File and Console
|
||||
string date = DateTime.Now.ToString("yyyyMMdd.HHmmss");
|
||||
string AppLogFilename = Path.Combine(Program.AppLogPath, $"DisplayMagician-{date}.log");
|
||||
string AppLogFilename = Path.Combine(Program.AppLogPath, $"DisplayMagician.log");
|
||||
|
||||
// Create the Shortcut Icon Cache if it doesn't exist so that it's avilable for all the program
|
||||
if (!Directory.Exists(AppLogPath))
|
||||
@ -80,9 +73,34 @@ namespace DisplayMagician {
|
||||
};
|
||||
var logconsole = new NLog.Targets.ConsoleTarget("logconsole");
|
||||
|
||||
// Load the program settings
|
||||
AppProgramSettings = ProgramSettings.LoadSettings();
|
||||
|
||||
// Rules for mapping loggers to targets
|
||||
NLog.LogLevel logLevel = null;
|
||||
switch (AppProgramSettings.LogLevel)
|
||||
{
|
||||
case "Trace":
|
||||
logLevel = NLog.LogLevel.Trace;
|
||||
break;
|
||||
case "Info":
|
||||
logLevel = NLog.LogLevel.Info;
|
||||
break;
|
||||
case "Warn":
|
||||
logLevel = NLog.LogLevel.Warn;
|
||||
break;
|
||||
case "Error":
|
||||
logLevel = NLog.LogLevel.Error;
|
||||
break;
|
||||
case "Debug":
|
||||
logLevel = NLog.LogLevel.Debug;
|
||||
break;
|
||||
default:
|
||||
logLevel = NLog.LogLevel.Warn;
|
||||
break;
|
||||
}
|
||||
config.AddRule(NLog.LogLevel.Info, NLog.LogLevel.Fatal, logconsole);
|
||||
config.AddRule(NLog.LogLevel.Debug, NLog.LogLevel.Fatal, logfile);
|
||||
config.AddRule(logLevel, NLog.LogLevel.Fatal, logfile);
|
||||
|
||||
// Apply config
|
||||
NLog.LogManager.Configuration = config;
|
||||
@ -103,8 +121,6 @@ namespace DisplayMagician {
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
// Load the program settings
|
||||
AppProgramSettings = ProgramSettings.LoadSettings();
|
||||
|
||||
var app = new CommandLineApplication();
|
||||
|
||||
|
@ -5,9 +5,11 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
|
||||
namespace DisplayMagician
|
||||
{
|
||||
|
||||
public class ProgramSettings
|
||||
{
|
||||
#region Class Variables
|
||||
@ -19,6 +21,7 @@ namespace DisplayMagician
|
||||
|
||||
#region Instance Variables
|
||||
private bool _minimiseOnStart = false;
|
||||
private string _logLevel = NLog.LogLevel.Warn.ToString();
|
||||
#endregion
|
||||
|
||||
#region Class Properties
|
||||
@ -38,6 +41,45 @@ namespace DisplayMagician
|
||||
}
|
||||
}
|
||||
|
||||
public string LogLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return _logLevel;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
||||
switch (value.ToLower())
|
||||
{
|
||||
case "trace":
|
||||
_logLevel = NLog.LogLevel.Trace.ToString();
|
||||
break;
|
||||
case "debug":
|
||||
_logLevel = NLog.LogLevel.Debug.ToString();
|
||||
break;
|
||||
case "info":
|
||||
_logLevel = NLog.LogLevel.Info.ToString();
|
||||
break;
|
||||
case "warn":
|
||||
_logLevel = NLog.LogLevel.Warn.ToString();
|
||||
break;
|
||||
case "Error":
|
||||
_logLevel = NLog.LogLevel.Error.ToString();
|
||||
break;
|
||||
default:
|
||||
_logLevel = NLog.LogLevel.Warn.ToString();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// Because a value has changed, we need to save the setting
|
||||
// to remember it for later.
|
||||
if (_programSettingsLoaded)
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public static Version FileVersion
|
||||
{
|
||||
get => new Version(1, 0, 0);
|
||||
@ -76,6 +118,11 @@ namespace DisplayMagician
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
programSettings = new ProgramSettings();
|
||||
programSettings.SaveSettings();
|
||||
}
|
||||
|
||||
// If there isn't any settings in the file then create a new ProgramSettings object
|
||||
if (programSettings == null)
|
||||
|
@ -29,6 +29,7 @@ namespace DisplayMagician
|
||||
private static string _shortcutStorageJsonFileName = Path.Combine(AppShortcutStoragePath, $"Shortcuts_{Version.ToString(2)}.json");
|
||||
private static string uuidV4Regex = @"(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$";
|
||||
private static CoreAudioController _audioController = null;
|
||||
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
#endregion
|
||||
|
||||
#region Class Constructors
|
||||
@ -48,7 +49,8 @@ namespace DisplayMagician
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"ShortcutItem/Instansiation exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
||||
//Console.WriteLine($"ShortcutItem/Instansiation exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
||||
logger.Error(ex, $"ShortcutRepository/Instansiation exception during class construction");
|
||||
// ignored
|
||||
}
|
||||
|
||||
@ -413,6 +415,7 @@ namespace DisplayMagician
|
||||
(bool valid, string reason) = shortcutToUse.IsValid();
|
||||
if (!valid)
|
||||
{
|
||||
logger.Error($"ShortcutRepository/RunShortcut error. shortcutToUse isn't valid");
|
||||
MessageBox.Show(
|
||||
$"Unable to run the shortcut '{shortcutToUse.Name}': {reason}",
|
||||
@"Cannot run the Shortcut",
|
||||
@ -443,6 +446,7 @@ namespace DisplayMagician
|
||||
if (!Program.ApplyProfile(shortcutToUse.ProfileToUse))
|
||||
{
|
||||
Console.WriteLine($"ERROR - Cannot apply '{shortcutToUse.ProfileToUse.Name}' Display Profile");
|
||||
logger.Error($"ShortcutRepository/RunShortcut cannot apply '{shortcutToUse.ProfileToUse.Name}' Display Profile");
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,7 +520,7 @@ namespace DisplayMagician
|
||||
// This means we need to save the state if the temporaryIcon
|
||||
// is false.
|
||||
// Conversely, if temporaryIcon is true, then we need
|
||||
// to create a NotifyIncon as MainFOrm isn't running to create
|
||||
// to create a NotifyIncon as MainForm isn't running to create
|
||||
// one for us already!
|
||||
if (notifyIcon == null)
|
||||
temporaryNotifyIcon = true;
|
||||
@ -539,6 +543,7 @@ namespace DisplayMagician
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"ShortcutRepository/RunShortcut exception: Trying to {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
||||
logger.Error(ex, $"ShortcutRepository/RunShortcut exception setting NotifyIcon");
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
@ -632,6 +637,7 @@ namespace DisplayMagician
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Console.WriteLine($"ShortcutRepository/RunShortcut exception 2: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
|
||||
logger.Error(ex, $"ShortcutRepository/RunShortcut exception waiting for the monitored process to exit");
|
||||
processExitCount++;
|
||||
}
|
||||
}
|
||||
@ -662,6 +668,7 @@ namespace DisplayMagician
|
||||
{
|
||||
address += "/" + shortcutToUse.GameArguments;
|
||||
}
|
||||
logger.Debug($"ShortcutRepository/RunShortcut Steam launch address is {address}");
|
||||
|
||||
// Start the URI Handler to run Steam
|
||||
Console.WriteLine($"Starting Steam Game: {steamGameToRun.Name}");
|
||||
@ -695,13 +702,10 @@ namespace DisplayMagician
|
||||
notifyIcon.Text = $"DisplayMagician: Running {steamGameToRun.Name.Substring(0, 41)}...";
|
||||
Application.DoEvents();
|
||||
|
||||
// Wait 300ms for the game process to spawn
|
||||
Thread.Sleep(300);
|
||||
// Now check it's actually started
|
||||
if (steamGameToRun.IsRunning)
|
||||
{
|
||||
|
||||
// Wait for the game to exit
|
||||
Console.WriteLine($"Waiting for {steamGameToRun.Name} to exit.");
|
||||
logger.Info($"ShortcutRepository/RunShortcut - waiting for Steam Game {steamGameToRun.Name} to exit.");
|
||||
while (true)
|
||||
{
|
||||
if (!steamGameToRun.IsRunning)
|
||||
@ -712,7 +716,7 @@ namespace DisplayMagician
|
||||
Thread.Sleep(300);
|
||||
}
|
||||
Console.WriteLine($"{steamGameToRun.Name} has exited.");
|
||||
}
|
||||
logger.Info($"ShortcutRepository/RunShortcut - Steam Game {steamGameToRun.Name} has exited.");
|
||||
|
||||
}
|
||||
|
||||
@ -729,6 +733,7 @@ namespace DisplayMagician
|
||||
// Prepare to start the steam game using the URI interface
|
||||
// as used by Steam for it's own desktop shortcuts.
|
||||
var address = $"uplay://launch/{uplayGameToRun.Id}";
|
||||
logger.Debug($"ShortcutRepository/RunShortcut Uplay launch address is {address}");
|
||||
if (shortcutToUse.GameArgumentsRequired)
|
||||
{
|
||||
address += "/" + shortcutToUse.GameArguments;
|
||||
@ -760,16 +765,15 @@ namespace DisplayMagician
|
||||
IPCService.GetInstance().Status = InstanceStatus.OnHold;
|
||||
|
||||
// Add a status notification icon in the status area
|
||||
notifyIcon.Text = $"DisplayMagician: Running {uplayGameToRun.Name.Substring(0,41)}...";
|
||||
if (uplayGameToRun.Name.Length <= 41)
|
||||
notifyIcon.Text = $"DisplayMagician: Running {uplayGameToRun.Name}...";
|
||||
else
|
||||
notifyIcon.Text = $"DisplayMagician: Running {uplayGameToRun.Name.Substring(0, 41)}...";
|
||||
Application.DoEvents();
|
||||
|
||||
// Wait 300ms for the game process to spawn
|
||||
Thread.Sleep(300);
|
||||
// Now check it's actually started
|
||||
if (uplayGameToRun.IsRunning)
|
||||
{
|
||||
// Wait for the game to exit
|
||||
Console.WriteLine($"Waiting for {uplayGameToRun.Name} to exit.");
|
||||
logger.Info($"ShortcutRepository/RunShortcut - waiting for Uplay Game {uplayGameToRun.Name} to exit.");
|
||||
while (true)
|
||||
{
|
||||
if (!uplayGameToRun.IsRunning)
|
||||
@ -780,8 +784,7 @@ namespace DisplayMagician
|
||||
Thread.Sleep(300);
|
||||
}
|
||||
Console.WriteLine($"{uplayGameToRun.Name} has exited.");
|
||||
}
|
||||
|
||||
logger.Info($"ShortcutRepository/RunShortcut - Uplay Game {uplayGameToRun.Name} has exited.");
|
||||
}
|
||||
|
||||
|
||||
@ -884,5 +887,4 @@ namespace DisplayMagician
|
||||
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user