2017-02-26 19:23:31 +00:00
using System ;
2020-04-19 05:37:29 +00:00
using McMaster.Extensions.CommandLineUtils ;
2017-02-26 19:23:31 +00:00
using System.IO ;
using System.Linq ;
2018-10-20 00:20:53 +00:00
using System.Net ;
2020-04-19 05:37:29 +00:00
using System.Reflection ;
2017-02-26 19:23:31 +00:00
using System.Threading.Tasks ;
using System.Windows.Forms ;
2020-12-02 08:11:23 +00:00
using DisplayMagician.InterProcess ;
using DisplayMagician.Resources ;
2020-12-20 07:42:04 +00:00
using DisplayMagicianShared ;
2020-12-02 08:11:23 +00:00
using DisplayMagician.UIForms ;
2021-04-19 08:50:29 +00:00
using DisplayMagician.GameLibraries ;
2020-05-17 09:19:55 +00:00
using System.Text.RegularExpressions ;
2020-06-14 04:20:52 +00:00
using System.Drawing ;
2020-12-20 02:21:53 +00:00
using DesktopNotifications ;
2020-12-26 08:46:32 +00:00
using System.Runtime.Serialization ;
2021-02-20 09:03:19 +00:00
using NLog.Config ;
2021-04-19 10:32:58 +00:00
using System.Collections.Generic ;
2021-05-15 09:58:46 +00:00
using System.Collections ;
2017-02-26 19:23:31 +00:00
2020-12-02 08:11:23 +00:00
namespace DisplayMagician {
2020-04-22 11:46:31 +00:00
2021-03-28 07:25:01 +00:00
public enum ApplyProfileResult
{
Successful ,
Cancelled ,
Error
}
2017-02-26 19:23:31 +00:00
internal static class Program
{
2020-12-02 08:11:23 +00:00
internal static string AppDataPath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) , "DisplayMagician" ) ;
2020-12-26 03:59:45 +00:00
public static string AppStartupPath = Application . StartupPath ;
2020-06-14 04:20:52 +00:00
public static string AppIconPath = Path . Combine ( Program . AppDataPath , $"Icons" ) ;
2020-08-18 22:16:04 +00:00
public static string AppProfilePath = Path . Combine ( Program . AppDataPath , $"Profiles" ) ;
public static string AppShortcutPath = Path . Combine ( Program . AppDataPath , $"Shortcuts" ) ;
2020-12-08 08:20:26 +00:00
public static string AppLogPath = Path . Combine ( Program . AppDataPath , $"Logs" ) ;
2020-12-02 08:11:23 +00:00
public static string AppDisplayMagicianIconFilename = Path . Combine ( AppIconPath , @"DisplayMagician.ico" ) ;
2020-06-14 04:20:52 +00:00
public static string AppOriginIconFilename = Path . Combine ( AppIconPath , @"Origin.ico" ) ;
public static string AppSteamIconFilename = Path . Combine ( AppIconPath , @"Steam.ico" ) ;
2020-10-25 23:39:14 +00:00
public static string AppUplayIconFilename = Path . Combine ( AppIconPath , @"Uplay.ico" ) ;
2020-06-14 04:20:52 +00:00
public static string AppEpicIconFilename = Path . Combine ( AppIconPath , @"Epic.ico" ) ;
2020-12-26 03:59:45 +00:00
public static bool AppToastActivated = false ;
2020-11-19 09:40:08 +00:00
public static bool WaitingForGameToExit = false ;
2020-10-26 04:08:55 +00:00
public static ProgramSettings AppProgramSettings ;
2020-12-23 08:13:21 +00:00
public static MainForm AppMainForm ;
2020-05-09 13:02:07 +00:00
2020-12-08 08:20:26 +00:00
private static readonly NLog . Logger logger = NLog . LogManager . GetCurrentClassLogger ( ) ;
2021-02-10 09:40:22 +00:00
private static SharedLogger sharedLogger ;
2020-12-08 08:20:26 +00:00
2017-02-26 19:23:31 +00:00
/// <summary>
/// The main entry point for the application.
/// </summary>
2020-04-13 10:10:35 +00:00
[STAThread]
private static int Main ( string [ ] args )
2017-02-26 19:23:31 +00:00
{
2020-04-13 10:10:35 +00:00
2020-12-19 23:35:36 +00:00
// This sets the Application User Model ID to "LittleBitBig.DisplayMagician" so that
// Windows 10 recognises the application, and allows features such as Toasts,
// taskbar pinning and similar.
2020-12-20 02:21:53 +00:00
// Register AUMID, COM server, and activator
DesktopNotificationManagerCompat . RegisterAumidAndComServer < DesktopNotificationActivator > ( ShellUtils . AUMID ) ;
DesktopNotificationManagerCompat . RegisterActivator < DesktopNotificationActivator > ( ) ;
2020-12-19 23:35:36 +00:00
2020-12-08 08:20:26 +00:00
// Prepare NLog for logging
2021-02-20 10:14:16 +00:00
2021-03-06 04:55:04 +00:00
//NLog.Common.InternalLogger.LogLevel = NLog.LogLevel.Debug;
//NLog.Common.InternalLogger.LogToConsole = true;
//NLog.Common.InternalLogger.LogFile = "C:\\Users\\terry\\AppData\\Local\\DisplayMagician\\Logs\\nlog-internal.txt";
2021-02-20 10:14:16 +00:00
2020-12-08 08:20:26 +00:00
var config = new NLog . Config . LoggingConfiguration ( ) ;
// Targets where to log to: File and Console
2020-12-27 21:34:15 +00:00
//string date = DateTime.Now.ToString("yyyyMMdd.HHmmss");
2020-12-09 07:47:30 +00:00
string AppLogFilename = Path . Combine ( Program . AppLogPath , $"DisplayMagician.log" ) ;
2020-12-08 08:20:26 +00:00
2020-12-27 21:34:15 +00:00
// Create the Logging Dir if it doesn't exist so that it's avilable for all
// parts of the program to use
2020-12-08 08:20:26 +00:00
if ( ! Directory . Exists ( AppLogPath ) )
{
try
{
Directory . CreateDirectory ( AppLogPath ) ;
}
catch ( Exception ex )
{
2021-02-10 09:40:22 +00:00
Console . WriteLine ( $"Program/StartUpNormally exception: Cannot create the Application Log Folder {AppLogPath} - {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-12-08 08:20:26 +00:00
}
}
2021-02-20 09:03:19 +00:00
2020-12-09 07:47:30 +00:00
// 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 :
2021-02-20 08:04:58 +00:00
logLevel = NLog . LogLevel . Info ;
2020-12-09 07:47:30 +00:00
break ;
}
2021-02-20 09:03:19 +00:00
// Create the log file target
var logfile = new NLog . Targets . FileTarget ( "logfile" )
{
FileName = AppLogFilename ,
DeleteOldFileOnStartup = true
} ;
// Create a logging rule to use the log file target
var loggingRule = new LoggingRule ( "LogToFile" ) ;
loggingRule . EnableLoggingForLevels ( logLevel , NLog . LogLevel . Fatal ) ;
loggingRule . Targets . Add ( logfile ) ;
2021-02-20 10:14:16 +00:00
loggingRule . LoggerNamePattern = "*" ;
2021-02-20 09:03:19 +00:00
config . LoggingRules . Add ( loggingRule ) ;
// Create the log console target
2021-02-20 10:14:16 +00:00
var logconsole = new NLog . Targets . ColoredConsoleTarget ( "logconsole" )
2021-02-20 09:03:19 +00:00
{
Layout = "${date:format=HH\\:MM\\:ss} ${logger} ${message}" ,
} ;
// Create a logging rule to use the log console target
2021-02-20 10:14:16 +00:00
var loggingRule2 = new LoggingRule ( "LogToConsole" ) ;
loggingRule2 . EnableLoggingForLevels ( NLog . LogLevel . Info , NLog . LogLevel . Fatal ) ;
loggingRule2 . Targets . Add ( logconsole ) ;
loggingRule . LoggerNamePattern = "*" ;
config . LoggingRules . Add ( loggingRule2 ) ;
2020-12-08 08:20:26 +00:00
// Apply config
NLog . LogManager . Configuration = config ;
2021-02-10 09:40:22 +00:00
// Make DisplayMagicianShared use the same log file by sending it the
// details of the existing NLog logger
sharedLogger = new SharedLogger ( logger ) ;
2020-12-08 08:20:26 +00:00
2021-02-10 09:40:22 +00:00
// Start the Log file
logger . Info ( $"Starting {Application.ProductName} v{Application.ProductVersion}" ) ;
2020-12-08 08:20:26 +00:00
2021-04-04 09:49:37 +00:00
// Create the other DM Dir if it doesn't exist so that it's avilable for all
// parts of the program to use
if ( ! Directory . Exists ( AppIconPath ) )
{
try
{
Directory . CreateDirectory ( AppIconPath ) ;
}
catch ( Exception ex )
{
logger . Error ( ex , $"Program/StartUpNormally exception: Cannot create the Application Icon Folder {AppLogPath}" ) ;
}
}
if ( ! Directory . Exists ( AppProfilePath ) )
{
try
{
Directory . CreateDirectory ( AppProfilePath ) ;
}
catch ( Exception ex )
{
logger . Error ( ex , $"Program/StartUpNormally exception: Cannot create the Application Profile Folder {AppProfilePath}" ) ;
}
}
if ( ! Directory . Exists ( AppShortcutPath ) )
{
try
{
Directory . CreateDirectory ( AppShortcutPath ) ;
}
catch ( Exception ex )
{
logger . Error ( ex , $"Program/StartUpNormally exception: Cannot create the Application Shortcut Folder {AppShortcutPath}" ) ;
}
}
2020-04-28 10:38:43 +00:00
// Write the Application Name
Console . WriteLine ( $"{Application.ProductName} v{Application.ProductVersion}" ) ;
for ( int i = 0 ; i < = Application . ProductName . Length + Application . ProductVersion . Length ; i + + )
{
Console . Write ( "=" ) ;
}
Console . WriteLine ( "=" ) ;
2020-07-21 11:40:33 +00:00
Console . WriteLine ( $"Copyright <20> Terry MacDonald 2020-{DateTime.Today.Year}" ) ;
2020-10-25 23:39:14 +00:00
Console . WriteLine ( @"Derived from Helios Display Management - Copyright <20> Soroush Falahati 2017-2020" ) ;
2020-04-28 10:38:43 +00:00
2020-10-19 08:50:42 +00:00
//Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application . EnableVisualStyles ( ) ;
Application . SetCompatibleTextRenderingDefault ( false ) ;
2021-04-23 09:25:42 +00:00
ServicePointManager . SecurityProtocol = SecurityProtocolType . Tls12 ;
2020-10-19 08:50:42 +00:00
2021-02-10 09:40:22 +00:00
logger . Debug ( $"Setting up commandline processing configuration" ) ;
2020-12-26 03:59:45 +00:00
var app = new CommandLineApplication
{
AllowArgumentSeparator = true ,
UnrecognizedArgumentHandling = UnrecognizedArgumentHandling . StopParsingAndCollect ,
} ;
2020-04-13 10:10:35 +00:00
2020-04-19 05:37:29 +00:00
app . Description = "This application helps configure your NVIDIA Videocard for multiple displays." ;
app . ExtendedHelpText = "This application helps configure your NVIDIA Videocard for multiple displays. It has some nifty features such as the "
+ Environment . NewLine + " ability to temporarily change your screen settings while you are playing a game, and then change them back once finished." ;
2017-02-26 19:23:31 +00:00
2020-04-19 05:37:29 +00:00
app . GetFullNameAndVersion ( ) ;
app . MakeSuggestionsInErrorMessage = true ;
2020-04-28 10:38:43 +00:00
app . HelpOption ( "-?|-h|--help" , inherited : true ) ;
2020-04-16 10:49:11 +00:00
2020-04-19 05:37:29 +00:00
app . VersionOption ( "-v|--version" , ( ) = > {
return string . Format ( "Version {0}" , Assembly . GetExecutingAssembly ( ) . GetName ( ) . Version ) ;
} ) ;
2020-04-13 10:10:35 +00:00
2021-05-20 05:41:38 +00:00
CommandOption debug = app . Option ( "--debug" , "Generate a DisplayMagician.log debug-level log file" , CommandOptionType . NoValue ) ;
CommandOption trace = app . Option ( "--trace" , "Generate a DisplayMagician.log trace-level log file" , CommandOptionType . NoValue ) ;
2020-07-21 11:40:33 +00:00
// This is the RunShortcut command
2020-12-02 09:06:50 +00:00
app . Command ( DisplayMagicianStartupAction . RunShortcut . ToString ( ) , ( runShortcutCmd ) = >
2020-04-14 10:18:52 +00:00
{
2021-05-20 05:41:38 +00:00
if ( trace . HasValue ( ) )
{
Console . WriteLine ( $"Changing logging level to TRACE level as --trace was provided on the commandline." ) ;
logger . Info ( $"Changing logging level to TRACE level as --trace was provided on the commandline." ) ;
loggingRule . SetLoggingLevels ( NLog . LogLevel . Trace , NLog . LogLevel . Fatal ) ;
NLog . LogManager . ReconfigExistingLoggers ( ) ;
}
else if ( debug . HasValue ( ) )
{
Console . WriteLine ( $"Changing logging level to DEBUG level as --debug was provided on the commandline." ) ;
logger . Info ( $"Changing logging level to DEBUG level as --debug was provided on the commandline." ) ;
loggingRule . SetLoggingLevels ( NLog . LogLevel . Debug , NLog . LogLevel . Fatal ) ;
NLog . LogManager . ReconfigExistingLoggers ( ) ;
}
2020-10-11 08:12:52 +00:00
var argumentShortcut = runShortcutCmd . Argument ( "\"SHORTCUT_UUID\"" , "(required) The UUID of the shortcut to run from those stored in the shortcut library." ) . IsRequired ( ) ;
2020-05-17 09:19:55 +00:00
argumentShortcut . Validators . Add ( new ShortcutMustExistValidator ( ) ) ;
2020-04-19 05:37:29 +00:00
//description and help text of the command.
2020-10-11 08:12:52 +00:00
runShortcutCmd . Description = "Use this command to run favourite game or application with a display profile of your choosing." ;
2018-10-20 00:27:25 +00:00
2020-10-11 08:12:52 +00:00
runShortcutCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
2021-02-10 09:40:22 +00:00
logger . Debug ( $"RunShortcut commandline command was invoked!" ) ;
2020-07-21 11:40:33 +00:00
//
RunShortcut ( argumentShortcut . Value ) ;
2020-05-17 09:19:55 +00:00
return 0 ;
2020-04-19 05:37:29 +00:00
} ) ;
} ) ;
2020-11-22 08:27:29 +00:00
// This is the ChangeProfile command
2020-12-02 09:06:50 +00:00
app . Command ( DisplayMagicianStartupAction . ChangeProfile . ToString ( ) , ( runProfileCmd ) = >
2020-11-22 07:49:37 +00:00
{
2021-05-20 05:41:38 +00:00
if ( trace . HasValue ( ) )
{
Console . WriteLine ( $"Changing logging level to TRACE level as --trace was provided on the commandline." ) ;
logger . Info ( $"Changing logging level to TRACE level as --trace was provided on the commandline." ) ;
loggingRule . SetLoggingLevels ( NLog . LogLevel . Trace , NLog . LogLevel . Fatal ) ;
NLog . LogManager . ReconfigExistingLoggers ( ) ;
}
else if ( debug . HasValue ( ) )
{
Console . WriteLine ( $"Changing logging level to DEBUG level as --debug was provided on the commandline." ) ;
logger . Info ( $"Changing logging level to DEBUG level as --debug was provided on the commandline." ) ;
loggingRule . SetLoggingLevels ( NLog . LogLevel . Debug , NLog . LogLevel . Fatal ) ;
NLog . LogManager . ReconfigExistingLoggers ( ) ;
}
2020-11-22 08:27:29 +00:00
var argumentProfile = runProfileCmd . Argument ( "\"Profile_UUID\"" , "(required) The UUID of the profile to run from those stored in the profile file." ) . IsRequired ( ) ;
argumentProfile . Validators . Add ( new ProfileMustExistValidator ( ) ) ;
2020-11-22 07:49:37 +00:00
//description and help text of the command.
2020-11-22 08:27:29 +00:00
runProfileCmd . Description = "Use this command to change to a display profile of your choosing." ;
2020-11-22 07:49:37 +00:00
2020-11-22 08:27:29 +00:00
runProfileCmd . OnExecute ( ( ) = >
2020-11-22 07:49:37 +00:00
{
2021-02-10 09:40:22 +00:00
logger . Debug ( $"ChangeProfile commandline command was invoked!" ) ;
2020-11-22 08:27:29 +00:00
try
{
// Lookup the profile
ProfileItem profileToUse = ProfileRepository . AllProfiles . Where ( p = > p . UUID . Equals ( argumentProfile . Value ) ) . First ( ) ;
ApplyProfile ( profileToUse ) ;
return 0 ;
}
2020-12-08 08:20:26 +00:00
catch ( Exception ex )
2020-11-22 08:27:29 +00:00
{
2020-12-08 08:20:26 +00:00
logger . Error ( ex , $"Program/Main exception running ApplyProfile(profileToUse)" ) ;
2020-11-22 08:27:29 +00:00
return 1 ;
}
2020-11-22 07:49:37 +00:00
} ) ;
} ) ;
2020-12-06 08:19:03 +00:00
// This is the CreateProfile command
app . Command ( DisplayMagicianStartupAction . CreateProfile . ToString ( ) , ( createProfileCmd ) = >
{
2021-05-20 05:41:38 +00:00
if ( trace . HasValue ( ) )
{
Console . WriteLine ( $"Changing logging level to TRACE level as --trace was provided on the commandline." ) ;
logger . Info ( $"Changing logging level to TRACE level as --trace was provided on the commandline." ) ;
loggingRule . SetLoggingLevels ( NLog . LogLevel . Trace , NLog . LogLevel . Fatal ) ;
NLog . LogManager . ReconfigExistingLoggers ( ) ;
}
else if ( debug . HasValue ( ) )
{
Console . WriteLine ( $"Changing logging level to DEBUG level as --debug was provided on the commandline." ) ;
logger . Info ( $"Changing logging level to DEBUG level as --debug was provided on the commandline." ) ;
loggingRule . SetLoggingLevels ( NLog . LogLevel . Debug , NLog . LogLevel . Fatal ) ;
NLog . LogManager . ReconfigExistingLoggers ( ) ;
}
2020-12-06 08:19:03 +00:00
//description and help text of the command.
createProfileCmd . Description = "Use this command to go directly to the create display profile screen." ;
createProfileCmd . OnExecute ( ( ) = >
{
2021-02-10 09:40:22 +00:00
logger . Debug ( $"CreateProfile commandline command was invoked!" ) ;
2020-12-06 08:33:00 +00:00
Console . WriteLine ( "Starting up and creating a new Display Profile..." ) ;
2021-02-10 09:40:22 +00:00
CreateProfile ( ) ;
2020-12-06 08:33:00 +00:00
return 0 ;
2020-12-06 08:19:03 +00:00
} ) ;
} ) ;
2020-04-22 11:46:31 +00:00
app . OnExecute ( ( ) = >
{
2021-05-20 05:41:38 +00:00
if ( trace . HasValue ( ) )
{
Console . WriteLine ( $"Changing logging level to TRACE level as --trace was provided on the commandline." ) ;
logger . Info ( $"Changing logging level to TRACE level as --trace was provided on the commandline." ) ;
loggingRule . SetLoggingLevels ( NLog . LogLevel . Trace , NLog . LogLevel . Fatal ) ;
NLog . LogManager . ReconfigExistingLoggers ( ) ;
}
else if ( debug . HasValue ( ) )
{
Console . WriteLine ( $"Changing logging level to DEBUG level as --debug was provided on the commandline." ) ;
logger . Info ( $"Changing logging level to DEBUG level as --debug was provided on the commandline." ) ;
loggingRule . SetLoggingLevels ( NLog . LogLevel . Debug , NLog . LogLevel . Fatal ) ;
NLog . LogManager . ReconfigExistingLoggers ( ) ;
}
2021-02-10 09:40:22 +00:00
logger . Debug ( $"No commandline command was invoked, so starting up normally" ) ;
2020-12-26 03:59:45 +00:00
// Add a workaround to handle the weird way that Windows tell us that DisplayMagician
// was started from a Notification Toast when closed (Windows 10)
// Due to the way that CommandLineUtils library works we need to handle this as
// 'Remaining Arguments'
if ( app . RemainingArguments ! = null & & app . RemainingArguments . Count > 0 )
{
foreach ( string myArg in app . RemainingArguments )
{
if ( myArg . Equals ( "-ToastActivated" ) )
{
2021-02-10 09:40:22 +00:00
logger . Debug ( $"We were started by the user clicking on a Windows Toast" ) ;
2020-12-26 03:59:45 +00:00
Program . AppToastActivated = true ;
break ;
}
}
}
2021-05-20 05:41:38 +00:00
logger . Info ( "Starting Normally..." ) ;
2020-12-06 08:33:00 +00:00
StartUpApplication ( ) ;
2020-04-22 11:46:31 +00:00
return 0 ;
} ) ;
2021-02-10 09:40:22 +00:00
logger . Debug ( $"Try to load all the Games in the background to avoid locking the UI" ) ;
2020-10-18 08:17:21 +00:00
// Try to load all the games in parallel to this process
Task . Run ( ( ) = > LoadGamesInBackground ( ) ) ;
2020-04-19 05:37:29 +00:00
try
{
2021-02-10 09:40:22 +00:00
logger . Debug ( $"Starting commandline processing" ) ;
2020-04-19 05:37:29 +00:00
// This begins the actual execution of the application
app . Execute ( args ) ;
}
catch ( CommandParsingException ex )
{
2020-12-08 08:20:26 +00:00
logger . Error ( ex , $"Program/Main exception parsing the Commands passed to the program" ) ;
2020-10-11 08:12:52 +00:00
Console . WriteLine ( "Didn't recognise the supplied commandline options: {0}" , ex . Message ) ;
2020-04-19 05:37:29 +00:00
}
catch ( Exception ex )
{
2020-10-25 23:39:14 +00:00
//Console.WriteLine($"Program/Main commandParsingException: {ex.Message}: {ex.StackTrace} - {ex.InnerException}");
// You'll always want to catch this exception, otherwise it will generate a messy and confusing error for the end user.
// the message will usually be something like:
// "Unrecognized command or argument '<invalid-command>'"
2020-12-08 08:20:26 +00:00
logger . Error ( ex , $"Program/Main general exception during app.Execute(args)" ) ;
2020-10-25 23:39:14 +00:00
Console . WriteLine ( $"Program/Main exception: Unable to execute application - {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-04-19 05:37:29 +00:00
}
2020-10-25 23:39:14 +00:00
2021-02-10 09:40:22 +00:00
logger . Debug ( $"Beginning to shutdown" ) ;
logger . Debug ( $"Clearing all previous windows toast notifications as they aren't needed any longer" ) ;
2020-12-23 05:29:20 +00:00
// Remove all the notifications we have set as they don't matter now!
DesktopNotificationManagerCompat . History . Clear ( ) ;
2020-12-08 08:20:26 +00:00
// Shutdown NLog
2021-02-10 09:40:22 +00:00
logger . Debug ( $"Stopping logging processes" ) ;
2020-12-08 08:20:26 +00:00
NLog . LogManager . Shutdown ( ) ;
2020-10-25 23:39:14 +00:00
// Exit with a 0 Errorlevel to indicate everything worked fine!
2020-04-19 05:37:29 +00:00
return 0 ;
2021-05-20 05:41:38 +00:00
}
2020-04-19 05:37:29 +00:00
2021-02-10 09:40:22 +00:00
private static void CreateProfile ( )
{
2021-02-13 20:18:49 +00:00
logger . Debug ( $"Program/CreateProfile: Starting" ) ;
2021-02-10 09:40:22 +00:00
try
{
// Start the IPC Service to
if ( ! IPCService . StartService ( ) )
{
throw new Exception ( Language . Can_not_open_a_named_pipe_for_Inter_process_communication ) ;
}
IPCService . GetInstance ( ) . Status = InstanceStatus . User ;
// Run the program with directly showing CreateProfile form
Application . Run ( new DisplayProfileForm ( ) ) ;
}
catch ( Exception ex )
{
Console . WriteLine ( $"Program/CreateProfile exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
logger . Error ( ex , $"Program/CreateProfile top level exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
MessageBox . Show (
ex . Message ,
Language . Fatal_Error ,
MessageBoxButtons . OK ,
MessageBoxIcon . Error ) ;
}
}
private static void StartUpApplication ( )
2020-04-19 05:37:29 +00:00
{
2021-02-13 20:18:49 +00:00
logger . Debug ( $"Program/StartUpApplication: Starting" ) ;
2020-04-19 05:37:29 +00:00
try
{
// Start the IPC Service to
if ( ! IPCService . StartService ( ) )
{
throw new Exception ( Language . Can_not_open_a_named_pipe_for_Inter_process_communication ) ;
2017-02-26 19:23:31 +00:00
}
2020-04-13 03:47:38 +00:00
2020-06-14 04:20:52 +00:00
// Create the Shortcut Icon Cache if it doesn't exist so that it's avilable for all the program
if ( ! Directory . Exists ( AppIconPath ) )
{
try
{
Directory . CreateDirectory ( AppIconPath ) ;
}
2020-07-15 08:11:38 +00:00
catch ( Exception ex )
2020-06-14 04:20:52 +00:00
{
2020-07-24 04:51:48 +00:00
Console . WriteLine ( $"Program/StartUpNormally exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-12-08 08:20:26 +00:00
logger . Error ( ex , $"Program/StartUpNormally exception while trying to create directory {AppIconPath}" ) ;
2020-06-14 04:20:52 +00:00
}
}
try
{
2020-12-02 08:11:23 +00:00
// Save a copy of the DisplayMagician Icon, and all the game library ones in preparation for future use
if ( ! File . Exists ( AppDisplayMagicianIconFilename ) )
2020-06-14 04:20:52 +00:00
{
2020-12-02 08:11:23 +00:00
Icon heliosIcon = ( Icon ) Properties . Resources . DisplayMagician ;
using ( FileStream fs = new FileStream ( AppDisplayMagicianIconFilename , FileMode . Create ) )
2020-06-14 04:20:52 +00:00
heliosIcon . Save ( fs ) ;
}
}
2020-07-15 08:11:38 +00:00
catch ( Exception ex )
2020-06-14 04:20:52 +00:00
{
2020-07-24 04:51:48 +00:00
Console . WriteLine ( $"Program/StartUpNormally exception 2: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-12-08 08:20:26 +00:00
logger . Error ( ex , $"Program/StartUpNormally exception create Icon files for future use in {AppIconPath}" ) ;
2020-06-14 04:20:52 +00:00
}
2020-12-06 08:33:00 +00:00
2020-04-19 05:37:29 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . User ;
2020-12-06 08:33:00 +00:00
// Run the program with normal startup
2021-02-10 09:40:22 +00:00
AppMainForm = new MainForm ( ) ;
Application . Run ( AppMainForm ) ;
2020-04-19 05:37:29 +00:00
2020-04-14 10:18:52 +00:00
}
2020-05-19 09:41:26 +00:00
catch ( Exception ex )
2020-04-14 10:18:52 +00:00
{
2020-07-24 04:51:48 +00:00
Console . WriteLine ( $"Program/StartUpNormally exception 3: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-12-28 10:17:13 +00:00
logger . Error ( ex , $"Program/StartUpNormally top level exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2020-04-14 10:18:52 +00:00
MessageBox . Show (
2020-05-19 09:41:26 +00:00
ex . Message ,
2020-04-14 10:18:52 +00:00
Language . Fatal_Error ,
MessageBoxButtons . OK ,
MessageBoxIcon . Error ) ;
}
2020-04-16 10:49:11 +00:00
2020-04-14 10:18:52 +00:00
}
2020-04-13 10:10:35 +00:00
2018-10-20 00:27:25 +00:00
2020-07-21 11:40:33 +00:00
// ReSharper disable once CyclomaticComplexity
private static void RunShortcut ( string shortcutUUID )
{
2021-02-13 20:18:49 +00:00
logger . Debug ( $"Program/RunShortcut: Starting" ) ;
2020-07-21 11:40:33 +00:00
ShortcutItem shortcutToRun = null ;
2018-10-20 00:27:25 +00:00
2020-07-21 11:40:33 +00:00
// Check there is only one version of this application so we won't
// mess with another monitoring session
2017-02-26 19:23:31 +00:00
if (
IPCClient . QueryAll ( )
. Any (
client = >
2018-10-20 00:27:25 +00:00
client . Status = = InstanceStatus . Busy | |
client . Status = = InstanceStatus . OnHold ) )
{
2017-02-26 19:23:31 +00:00
throw new Exception (
Language
. Another_instance_of_this_program_is_in_working_state_Please_close_other_instances_before_trying_to_switch_profile ) ;
2018-10-20 00:27:25 +00:00
}
2020-07-21 11:40:33 +00:00
// Match the ShortcutName to the actual shortcut listed in the shortcut library
// And error if we can't find it.
if ( ShortcutRepository . ContainsShortcut ( shortcutUUID ) )
2017-02-26 19:23:31 +00:00
{
2020-07-21 11:40:33 +00:00
// make sure we trim the "" if there are any
shortcutUUID = shortcutUUID . Trim ( '"' ) ;
shortcutToRun = ShortcutRepository . GetShortcut ( shortcutUUID ) ;
2020-04-19 05:37:29 +00:00
}
2020-07-21 11:40:33 +00:00
else
2020-04-19 05:37:29 +00:00
{
2020-07-21 11:40:33 +00:00
throw new Exception ( Language . Cannot_find_shortcut_in_library ) ;
2020-04-19 05:37:29 +00:00
}
2018-10-20 00:27:25 +00:00
2020-07-23 06:31:00 +00:00
if ( shortcutToRun is ShortcutItem )
2020-04-19 05:37:29 +00:00
{
2020-07-23 06:31:00 +00:00
ShortcutRepository . RunShortcut ( shortcutToRun ) ;
2020-04-19 05:37:29 +00:00
}
2018-10-20 00:27:25 +00:00
2020-07-21 11:40:33 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . Busy ;
2020-04-19 05:37:29 +00:00
}
2020-05-17 09:19:55 +00:00
public static bool IsValidFilename ( string testName )
{
string strTheseAreInvalidFileNameChars = new string ( Path . GetInvalidFileNameChars ( ) ) ;
Regex regInvalidFileName = new Regex ( "[" + Regex . Escape ( strTheseAreInvalidFileNameChars ) + "]" ) ;
if ( regInvalidFileName . IsMatch ( testName ) ) { return false ; } ;
return true ;
}
2020-10-04 10:01:03 +00:00
// ApplyProfile lives here so that the UI works.
2021-03-28 07:25:01 +00:00
public static ApplyProfileResult ApplyProfile ( ProfileItem profile )
2020-05-17 09:19:55 +00:00
{
2021-02-13 20:18:49 +00:00
logger . Debug ( $"Program/ApplyProfile: Starting" ) ;
2020-10-04 10:01:03 +00:00
2021-03-07 04:11:46 +00:00
profile . RefreshPossbility ( ) ;
2020-10-04 10:01:03 +00:00
// We need to check if the profile is valid
if ( ! profile . IsPossible )
2021-02-13 20:18:49 +00:00
{
logger . Debug ( $"Program/ApplyProfile: The supplied profile {profile.Name} isn't currently possible to use, so we can't apply it. This means a display that existed before has been removed, or moved." ) ;
2021-03-28 07:25:01 +00:00
return ApplyProfileResult . Error ;
2021-02-13 20:18:49 +00:00
}
2020-10-04 10:01:03 +00:00
2020-11-22 08:45:04 +00:00
// We need to check if the profile is the same one that we're on
2021-03-07 04:11:46 +00:00
if ( profile . UUID = = ProfileRepository . GetActiveProfile ( ) . UUID )
2021-02-13 20:18:49 +00:00
{
logger . Debug ( $"Program/ApplyProfile: The supplied profile {profile.Name} is currently in use, so we don't need to apply it." ) ;
2021-03-28 07:25:01 +00:00
return ApplyProfileResult . Successful ;
2021-02-13 20:18:49 +00:00
}
2020-11-22 08:45:04 +00:00
2020-10-04 10:01:03 +00:00
try
{
2020-10-04 11:18:22 +00:00
// Now lets prepare changing the display topology task
Task applyTopologyTask = new Task ( ( ) = >
{
Console . WriteLine ( "Program/ApplyProfile : Applying Profile Topology " + profile . Name ) ;
2020-10-07 08:58:05 +00:00
if ( ! ProfileRepository . ApplyNVIDIAGridTopology ( profile ) )
2020-10-04 11:18:22 +00:00
{
// Somehow return that this profile topology didn't apply
2020-10-13 07:22:42 +00:00
throw new ApplyTopologyException ( "Program/ApplyProfile: ApplyNVIDIAGridTopology: Error setting up the NVIDIA Surround Grid Topology" ) ;
2020-10-04 11:18:22 +00:00
}
} ) ;
Task applyPathInfoTask = new Task ( ( ) = > {
Console . WriteLine ( "Program/ApplyProfile : Applying Profile Path " + profile . Name ) ;
2020-10-07 08:58:05 +00:00
if ( ! ProfileRepository . ApplyWindowsDisplayPathInfo ( profile ) )
2020-10-04 11:18:22 +00:00
{
// Somehow return that this profile path info didn't apply
2020-10-13 07:22:42 +00:00
throw new ApplyPathInfoException ( "Program/ApplyProfile: ApplyWindowsDisplayPathInfo: Error configuring the Windows Display Devices" ) ;
2020-10-04 11:18:22 +00:00
}
} ) ;
2020-10-04 10:01:03 +00:00
// Set up the UI forms to show
2020-10-06 10:49:10 +00:00
ApplyingProfileForm timeoutForm = new ApplyingProfileForm ( null , 3 , $"Changing to '{profile.Name}' Profile" , "Press ESC to cancel" , Color . Orange , true ) ;
2020-10-08 09:03:02 +00:00
ApplyingProfileForm topologyForm = new ApplyingProfileForm ( applyTopologyTask , 30 , $"Changing to '{profile.Name}' Profile" , "Applying NVIDIA Grid Topology" , Color . Aquamarine ) ;
ApplyingProfileForm pathInfoForm = new ApplyingProfileForm ( applyPathInfoTask , 15 , $"Changing to '{profile.Name}' Profile" , "Adjusting Windows Display Device positions" , Color . LawnGreen ) ;
2020-10-04 10:01:03 +00:00
2020-10-04 11:18:22 +00:00
if ( timeoutForm . ShowDialog ( ) = = DialogResult . Cancel )
2020-10-04 10:01:03 +00:00
{
2021-03-28 07:25:01 +00:00
return ApplyProfileResult . Cancelled ;
2020-10-04 11:18:22 +00:00
}
2020-10-07 08:58:05 +00:00
// We only want to do the topology change if the profile we're on now
// or the profile we're going to are NVIDIA surround profiles
int toProfileSurroundTopologyCount =
profile . Paths . SelectMany ( paths = > paths . TargetDisplays )
. Select ( target = > target . SurroundTopology )
. Where ( topology = > topology ! = null )
. Select ( topology = > topology . ToGridTopology ( ) )
. Count ( ) ;
2021-02-13 20:18:49 +00:00
if ( toProfileSurroundTopologyCount > 0 )
logger . Debug ( $"Program/ApplyProfile: {profile.Name} profile we want to use is a NVIDIA Surround profile, so we need to change the NVIDIA GRID topology." ) ;
else
logger . Debug ( $"Program/ApplyProfile: {profile.Name} profile we want to use does not use NVIDIA Surround." ) ;
2020-10-07 08:58:05 +00:00
int fromProfileSurroundTopologyCount =
ProfileRepository . CurrentProfile . Paths . SelectMany ( paths = > paths . TargetDisplays )
. Select ( target = > target . SurroundTopology )
. Where ( topology = > topology ! = null )
. Select ( topology = > topology . ToGridTopology ( ) )
. Count ( ) ;
2021-02-13 20:18:49 +00:00
if ( fromProfileSurroundTopologyCount > 0 )
logger . Debug ( $"Program/ApplyProfile: {ProfileRepository.CurrentProfile} profile currently in use is a NVIDIA Surround profile, so we need to change the NVIDIA GRID topology." ) ;
else
logger . Debug ( $"Program/ApplyProfile: {ProfileRepository.CurrentProfile} profile currently in use does not use NVIDIA Surround." ) ;
2020-10-07 08:58:05 +00:00
if ( toProfileSurroundTopologyCount > 0 | | fromProfileSurroundTopologyCount > 0 )
2020-10-06 07:07:21 +00:00
{
2021-02-13 20:18:49 +00:00
logger . Debug ( $"Program/ApplyProfile: Changing the NVIDIA GRID topology to apply or remove a NVIDIA Surround profile" ) ;
2020-10-07 08:58:05 +00:00
topologyForm . ShowDialog ( ) ;
try
2020-10-06 07:07:21 +00:00
{
2020-10-07 08:58:05 +00:00
applyTopologyTask . Wait ( ) ;
}
catch ( AggregateException ae )
{
2020-12-08 08:20:26 +00:00
logger . Error ( ae , $"Program/ApplyProfile exception during applyTopologyTask" ) ;
2020-10-07 08:58:05 +00:00
foreach ( var e in ae . InnerExceptions )
2020-10-06 07:07:21 +00:00
{
2020-10-07 08:58:05 +00:00
// Handle the custom exception.
if ( e is ApplyTopologyException )
{
Console . WriteLine ( e . Message ) ;
}
// Rethrow any other exception.
else
{
throw ;
}
2020-10-06 07:07:21 +00:00
}
}
2020-10-04 10:01:03 +00:00
2020-10-07 08:58:05 +00:00
if ( applyTopologyTask . IsFaulted )
Console . WriteLine ( "Program/ApplyProfile : Applying Profile Topology stage failed to complete" ) ;
2020-10-22 07:08:26 +00:00
if ( ! applyTopologyTask . IsCompleted )
2021-02-13 20:18:49 +00:00
{
logger . Debug ( $"Program/ApplyProfile: Failed to complete applying or removing the NVIDIA Surround profile" ) ;
2021-03-28 07:25:01 +00:00
return ApplyProfileResult . Error ;
2021-02-13 20:18:49 +00:00
}
2020-10-07 08:58:05 +00:00
}
2020-10-04 11:18:22 +00:00
2020-10-07 08:58:05 +00:00
// We always want to do the WindowsDisplayAPI PathInfo part
2021-02-13 20:18:49 +00:00
logger . Debug ( $"Program/ApplyProfile: Changing the Windows Display Path Info to change the Windows Display layout" ) ;
2020-10-04 11:18:22 +00:00
pathInfoForm . ShowDialog ( ) ;
2020-10-06 07:07:21 +00:00
try
{
applyPathInfoTask . Wait ( ) ;
}
catch ( AggregateException ae )
{
2020-12-08 08:20:26 +00:00
logger . Error ( ae , $"Program/ApplyProfile exception during applyPathInfoTask" ) ;
2020-10-06 07:07:21 +00:00
foreach ( var e in ae . InnerExceptions )
{
// Handle the custom exception.
if ( e is ApplyPathInfoException )
{
Console . WriteLine ( e . Message ) ;
}
// Rethrow any other exception.
else
{
throw ;
}
}
}
2020-10-04 11:18:22 +00:00
if ( applyPathInfoTask . IsFaulted )
2021-02-13 20:18:49 +00:00
logger . Debug ( $"Program/ApplyProfile: Applying Profile PathInfo stage failed to complete" ) ;
2020-10-04 11:18:22 +00:00
2020-10-22 07:08:26 +00:00
if ( ! applyPathInfoTask . IsCompleted )
2021-03-28 07:25:01 +00:00
return ApplyProfileResult . Error ;
2020-10-04 11:18:22 +00:00
2020-10-04 10:01:03 +00:00
}
catch ( Exception ex )
2020-05-17 09:19:55 +00:00
{
2020-10-04 10:01:03 +00:00
Console . WriteLine ( $"ProfileRepository/ApplyTopology exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}" ) ;
2021-02-13 20:18:49 +00:00
{
logger . Debug ( $"Program/ApplyProfile: Failed to complete changing the Windows Display layout" ) ;
2021-03-28 07:25:01 +00:00
return ApplyProfileResult . Error ;
2021-02-13 20:18:49 +00:00
}
2020-05-17 09:19:55 +00:00
}
2020-10-22 07:08:26 +00:00
2021-03-07 04:11:46 +00:00
ProfileRepository . UpdateActiveProfile ( ) ;
2021-03-28 07:25:01 +00:00
return ApplyProfileResult . Successful ;
2020-10-04 10:01:03 +00:00
}
2020-10-18 08:17:21 +00:00
public static bool LoadGamesInBackground ( )
{
2021-02-10 09:40:22 +00:00
logger . Debug ( $"Program/LoadGamesInBackground: Starting" ) ;
2020-10-18 08:17:21 +00:00
// Now lets prepare loading all the Steam games we have installed
2021-04-19 10:32:58 +00:00
Action loadSteamGamesAction = new Action ( ( ) = >
{
// Check if Steam is installed
GameLibrary steamLibrary = SteamLibrary . GetLibrary ( ) ;
if ( steamLibrary . IsGameLibraryInstalled )
{
// Load Steam library games
logger . Info ( $"Program/LoadGamesInBackground: Loading Installed Steam Games" ) ;
if ( ! steamLibrary . LoadInstalledGames ( ) )
{
logger . Info ( $"Program/LoadGamesInBackground: Cannot load installed Steam Games!" ) ;
}
logger . Info ( $"Program/LoadGamesInBackground: Loaded all Installed Steam Games (found {steamLibrary.InstalledGameCount})" ) ;
}
else
{
logger . Info ( $"Program/LoadGamesInBackground: Steam not installed." ) ;
Console . WriteLine ( "Steam not installed." ) ;
}
} ) ;
// Now lets prepare loading all the Uplay games we have installed
Action loadUplayGamesAction = new Action ( ( ) = >
{
// Check if Uplay is installed
GameLibrary uplayLibrary = UplayLibrary . GetLibrary ( ) ;
if ( uplayLibrary . IsGameLibraryInstalled )
{
// Load Uplay library games
logger . Info ( $"Program/LoadGamesInBackground: Loading Installed Uplay Games" ) ;
if ( ! uplayLibrary . LoadInstalledGames ( ) )
{
logger . Info ( $"Program/LoadGamesInBackground: Cannot load installed Uplay Games!" ) ;
}
logger . Info ( $"Program/LoadGamesInBackground: Loaded all Installed Uplay Games (found {uplayLibrary.InstalledGameCount})" ) ;
}
else
{
logger . Info ( $"Program/LoadGamesInBackground: Uplay not installed." ) ;
Console . WriteLine ( "Uplay not installed." ) ;
}
2021-04-16 10:40:58 +00:00
2021-04-19 10:32:58 +00:00
} ) ;
2020-10-18 08:17:21 +00:00
2021-04-19 10:32:58 +00:00
// Now lets prepare loading all the Origin games we have installed
Action loadOriginGamesAction = new Action ( ( ) = >
{
// Check if Origin is installed
GameLibrary originLibrary = OriginLibrary . GetLibrary ( ) ;
if ( originLibrary . IsGameLibraryInstalled )
{
// Load Origin library games
logger . Info ( $"Program/LoadGamesInBackground: Loading Installed Origin Games" ) ;
if ( ! originLibrary . LoadInstalledGames ( ) )
{
logger . Info ( $"Program/LoadGamesInBackground: Cannot load installed Origin Games!" ) ;
}
logger . Info ( $"Program/LoadGamesInBackground: Loaded all Installed Origin Games (found {originLibrary.InstalledGameCount})" ) ;
}
else
{
logger . Info ( $"Program/LoadGamesInBackground: Origin not installed." ) ;
Console . WriteLine ( "Origin not installed." ) ;
}
} ) ;
2021-06-05 04:58:00 +00:00
// Now lets prepare loading all the Epic games we have installed
Action loadEpicGamesAction = new Action ( ( ) = >
{
// Check if Epic is installed
GameLibrary epicLibrary = OriginLibrary . GetLibrary ( ) ;
if ( epicLibrary . IsGameLibraryInstalled )
{
// Load Origin library games
logger . Info ( $"Program/LoadGamesInBackground: Loading Installed Epic Games" ) ;
if ( ! epicLibrary . LoadInstalledGames ( ) )
{
2021-06-05 10:41:29 +00:00
logger . Info ( $"Program/LoadGamesInBackground: Cannot load installed Epic Games!" ) ;
2021-06-05 04:58:00 +00:00
}
logger . Info ( $"Program/LoadGamesInBackground: Loaded all Installed Epic Games (found {epicLibrary.InstalledGameCount})" ) ;
}
else
{
logger . Info ( $"Program/LoadGamesInBackground: Epic not installed." ) ;
Console . WriteLine ( "Epic not installed." ) ;
}
} ) ;
2021-06-05 10:41:29 +00:00
// Now lets prepare loading all the GOG games we have installed
Action loadGogGamesAction = new Action ( ( ) = >
{
// Check if GOG is installed
GameLibrary gogLibrary = GogLibrary . GetLibrary ( ) ;
if ( gogLibrary . IsGameLibraryInstalled )
{
// Load Origin library games
logger . Info ( $"Program/LoadGamesInBackground: Loading Installed GOG Games" ) ;
if ( ! gogLibrary . LoadInstalledGames ( ) )
{
logger . Info ( $"Program/LoadGamesInBackground: Cannot load installed GOG Games!" ) ;
}
logger . Info ( $"Program/LoadGamesInBackground: Loaded all Installed GOG Games (found {gogLibrary.InstalledGameCount})" ) ;
}
else
{
logger . Info ( $"Program/LoadGamesInBackground: GOG not installed." ) ;
Console . WriteLine ( "GOG not installed." ) ;
}
} ) ;
2021-04-19 10:32:58 +00:00
// Store all the actions in a array so we can wait on them later
List < Action > loadGamesActions = new List < Action > ( ) ;
loadGamesActions . Add ( loadSteamGamesAction ) ;
loadGamesActions . Add ( loadUplayGamesAction ) ;
loadGamesActions . Add ( loadOriginGamesAction ) ;
2021-06-05 04:58:00 +00:00
loadGamesActions . Add ( loadEpicGamesAction ) ;
2021-06-05 10:41:29 +00:00
loadGamesActions . Add ( loadGogGamesAction ) ;
2020-10-18 08:17:21 +00:00
try
{
2021-04-19 10:32:58 +00:00
logger . Debug ( $"Program/LoadGamesInBackground: Running game loading actions." ) ;
// Go through and start all the actions, making sure we only have one threat per action to avoid thread issues
int threads = loadGamesActions . Count ;
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = threads } ;
Parallel . Invoke ( options , loadGamesActions . ToArray ( ) ) ;
2021-02-10 09:40:22 +00:00
logger . Debug ( $"Program/LoadGamesInBackground: All game loading tasks finished" ) ;
2020-10-18 08:17:21 +00:00
}
catch ( AggregateException ae )
{
2021-04-19 10:32:58 +00:00
logger . Error ( ae , $"Program/LoadGamesInBackground exception during loadGamesActions" ) ;
2020-10-18 08:17:21 +00:00
}
2021-05-14 06:17:23 +00:00
// Produce a single array of Games we can reference later
GameLibrary . AllInstalledGamesInAllLibraries = SteamLibrary . GetLibrary ( ) . AllInstalledGames ;
GameLibrary . AllInstalledGamesInAllLibraries . AddRange ( UplayLibrary . GetLibrary ( ) . AllInstalledGames ) ;
GameLibrary . AllInstalledGamesInAllLibraries . AddRange ( OriginLibrary . GetLibrary ( ) . AllInstalledGames ) ;
2021-06-05 04:58:00 +00:00
GameLibrary . AllInstalledGamesInAllLibraries . AddRange ( EpicLibrary . GetLibrary ( ) . AllInstalledGames ) ;
2021-06-05 10:41:29 +00:00
GameLibrary . AllInstalledGamesInAllLibraries . AddRange ( GogLibrary . GetLibrary ( ) . AllInstalledGames ) ;
2021-05-14 06:17:23 +00:00
// Create Game Bitmaps from the Games so the rest of the program is faster later
// Get the bitmap out of the IconPath
// IconPath can be an ICO, or an EXE
foreach ( var game in GameLibrary . AllInstalledGamesInAllLibraries )
{
Bitmap bm = null ;
try
{
2021-05-18 10:03:02 +00:00
/ * ArrayList filesToSearchForIcon = new ArrayList ( ) ;
2021-05-16 09:46:58 +00:00
filesToSearchForIcon . Add ( game . ExePath ) ;
if ( game . IconPath ! = game . ExePath )
filesToSearchForIcon . Add ( game . IconPath ) ;
2021-05-14 09:22:29 +00:00
2021-05-18 10:03:02 +00:00
bm = ImageUtils . GetMeABitmapFromFile ( filesToSearchForIcon ) ; * /
2021-05-15 09:58:46 +00:00
2021-05-18 10:03:02 +00:00
// We only want the icon location that the GameLibrary told us to use
// Note: This may be an icon file, or an exe file.
// This function tries to get a 256x256 Vista sized bitmap from the file
2021-05-20 21:37:45 +00:00
logger . Trace ( $"Program/LoadGamesInBackground: Attempting to get game bitmaps from {game.Name}." ) ;
2021-05-18 10:03:02 +00:00
bm = ImageUtils . GetMeABitmapFromFile ( game . IconPath ) ;
2021-05-20 21:37:45 +00:00
if ( bm ! = null & & bm . GetType ( ) = = typeof ( Bitmap ) )
{
logger . Trace ( $"Program/LoadGamesInBackground: Got game bitmaps from {game.Name}." ) ;
}
else
{
logger . Trace ( $"Program/LoadGamesInBackground: Couldn't get game bitmaps from {game.Name} for some reason." ) ;
}
2021-05-15 09:58:46 +00:00
2021-05-14 06:17:23 +00:00
}
catch ( Exception ex )
{
2021-05-20 21:37:45 +00:00
logger . Error ( ex , $"Program/LoadGamesInBackground: Exception building game bitmaps for {game.Name} during load" ) ;
2021-05-16 09:46:58 +00:00
}
if ( bm = = null )
{
2021-05-14 06:17:23 +00:00
if ( game . GameLibrary . Equals ( SupportedGameLibraryType . Steam ) )
2021-05-19 08:40:26 +00:00
bm = Properties . Resources . Steam ;
2021-05-14 06:17:23 +00:00
else if ( game . GameLibrary . Equals ( SupportedGameLibraryType . Uplay ) )
2021-05-19 08:40:26 +00:00
bm = Properties . Resources . Uplay ;
2021-05-14 06:17:23 +00:00
else if ( game . GameLibrary . Equals ( SupportedGameLibraryType . Origin ) )
2021-05-19 08:40:26 +00:00
bm = Properties . Resources . Origin ;
2021-06-05 04:58:00 +00:00
else if ( game . GameLibrary . Equals ( SupportedGameLibraryType . Epic ) )
bm = Properties . Resources . Epic ;
2021-06-05 10:41:29 +00:00
else if ( game . GameLibrary . Equals ( SupportedGameLibraryType . GOG ) )
bm = Properties . Resources . GOG ;
2021-05-14 06:17:23 +00:00
else
bm = Properties . Resources . DisplayMagician . ToBitmap ( ) ;
}
2021-05-16 09:46:58 +00:00
2021-05-14 06:17:23 +00:00
game . GameBitmap = bm ;
}
2020-10-18 08:17:21 +00:00
return true ;
}
2021-05-20 22:55:23 +00:00
public static string HotkeyToString ( Keys hotkey )
{
string parsedHotkey = String . Empty ;
KeysConverter kc = new KeysConverter ( ) ;
// Lets parse the hotkey to create the text we need
parsedHotkey = kc . ConvertToString ( hotkey ) ;
// Control also shows as Ctrl+ControlKey, so we trim the +ControlKeu
if ( parsedHotkey . Contains ( "+ControlKey" ) )
parsedHotkey = parsedHotkey . Replace ( "+ControlKey" , "" ) ;
// Shift also shows as Shift+ShiftKey, so we trim the +ShiftKeu
if ( parsedHotkey . Contains ( "+ShiftKey" ) )
parsedHotkey = parsedHotkey . Replace ( "+ShiftKey" , "" ) ;
// Alt also shows as Alt+Menu, so we trim the +Menu
if ( parsedHotkey . Contains ( "+Menu" ) )
parsedHotkey = parsedHotkey . Replace ( "+Menu" , "" ) ;
return parsedHotkey ;
}
2017-02-26 19:23:31 +00:00
}
2020-10-06 07:07:21 +00:00
2020-10-18 08:17:21 +00:00
2020-10-06 07:07:21 +00:00
public class ApplyTopologyException : Exception
{
2020-12-26 08:46:32 +00:00
public ApplyTopologyException ( )
{ }
public ApplyTopologyException ( string message ) : base ( message )
{ }
public ApplyTopologyException ( string message , Exception innerException ) : base ( message , innerException )
{ }
public ApplyTopologyException ( SerializationInfo info , StreamingContext context ) : base ( info , context )
2020-10-06 07:07:21 +00:00
{ }
}
public class ApplyPathInfoException : Exception
{
2020-12-26 08:46:32 +00:00
public ApplyPathInfoException ( )
{ }
public ApplyPathInfoException ( string message ) : base ( message )
{ }
public ApplyPathInfoException ( string message , Exception innerException ) : base ( message , innerException )
{ }
public ApplyPathInfoException ( SerializationInfo info , StreamingContext context ) : base ( info , context )
2020-10-06 07:07:21 +00:00
{ }
}
2020-10-18 08:17:21 +00:00
public class LoadingInstalledGamesException : Exception
{
2020-12-26 08:46:32 +00:00
public LoadingInstalledGamesException ( )
{ }
public LoadingInstalledGamesException ( string message ) : base ( message )
{ }
public LoadingInstalledGamesException ( string message , Exception innerException ) : base ( message , innerException )
{ }
public LoadingInstalledGamesException ( SerializationInfo info , StreamingContext context ) : base ( info , context )
2020-10-18 08:17:21 +00:00
{ }
}
2017-02-26 19:23:31 +00:00
}