2017-02-26 19:23:31 +00:00
using System ;
using System.Collections.Generic ;
2020-04-19 05:37:29 +00:00
using System.ComponentModel.DataAnnotations ;
using McMaster.Extensions.CommandLineUtils ;
2017-02-26 19:23:31 +00:00
using System.Diagnostics ;
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 ;
2020-04-13 10:10:35 +00:00
using System.Runtime.CompilerServices ;
2017-02-26 19:23:31 +00:00
using System.Threading ;
using System.Threading.Tasks ;
using System.Windows.Forms ;
2020-04-23 08:16:16 +00:00
using HeliosPlus.InterProcess ;
using HeliosPlus.Resources ;
2020-04-27 10:55:44 +00:00
using HeliosPlus.GameLibraries ;
2020-04-23 08:16:16 +00:00
using HeliosPlus.Shared ;
using HeliosPlus.UIForms ;
2020-04-14 10:18:52 +00:00
using System.Net.NetworkInformation ;
2017-02-26 19:23:31 +00:00
2020-04-23 08:16:16 +00:00
namespace HeliosPlus {
2020-04-22 11:46:31 +00:00
public enum SupportedGameLibrary
{
Unknown ,
Steam ,
Uplay
}
2017-02-26 19:23:31 +00:00
internal static class Program
{
2020-04-13 03:47:38 +00:00
2020-05-09 13:02:07 +00:00
internal static string AppDataPath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) , "HeliosPlus" ) ;
2020-04-27 10:55:44 +00:00
internal static string ShortcutIconCachePath ;
2020-04-22 11:46:31 +00:00
2020-05-09 13:02:07 +00:00
2020-04-19 05:37:29 +00:00
internal static Profile GetProfile ( string profileName )
{
// Create an array of display profiles we have
2020-05-09 13:02:07 +00:00
var profiles = Profile . LoadAllProfiles ( ) . ToArray ( ) ;
2020-04-19 05:37:29 +00:00
// Check if the user supplied a --profile option using the profiles' ID
var profileIndex = profiles . Length > 0 ? Array . FindIndex ( profiles , p = > p . Id . Equals ( profileName , StringComparison . InvariantCultureIgnoreCase ) ) : - 1 ;
// If the profileID wasn't there, maybe they used the profile name?
if ( profileIndex = = - 1 )
{
// Try and lookup the profile in the profiles' Name fields
profileIndex = profiles . Length > 0 ? Array . FindIndex ( profiles , p = > p . Name . StartsWith ( profileName , StringComparison . InvariantCultureIgnoreCase ) ) : - 1 ;
}
return profiles [ profileIndex ] ;
}
2017-02-26 19:23:31 +00:00
internal static bool GoProfile ( Profile profile )
{
if ( profile . IsActive )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
return true ;
2018-10-20 00:27:25 +00:00
}
2017-08-10 14:21:45 +00:00
var instanceStatus = IPCService . GetInstance ( ) . Status ;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
try
{
IPCService . GetInstance ( ) . Status = InstanceStatus . Busy ;
var failed = false ;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
if ( new SplashForm ( ( ) = >
{
Task . Factory . StartNew ( ( ) = >
{
if ( ! profile . Apply ( ) )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
failed = true ;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
} , TaskCreationOptions . LongRunning ) ;
2018-10-20 00:27:25 +00:00
} , 3 , 30 ) . ShowDialog ( ) ! =
DialogResult . Cancel )
2017-02-26 19:23:31 +00:00
{
if ( failed )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
throw new Exception ( Language . Profile_is_invalid_or_not_possible_to_apply ) ;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
return true ;
}
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
return false ;
}
finally
{
2017-08-10 14:21:45 +00:00
IPCService . GetInstance ( ) . Status = instanceStatus ;
2017-02-26 19:23:31 +00:00
}
}
2020-04-19 05:37:29 +00:00
private static void CreateShortcutToExecutable ( Profile profile , string executableToRun , string processToMonitor , uint timeout , string executableArguments )
2017-02-26 19:23:31 +00:00
{
2020-04-19 05:37:29 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . User ;
new ShortcutForm ( profile )
2018-10-20 00:27:25 +00:00
{
2020-04-22 11:46:31 +00:00
ExecutableNameAndPath = executableToRun ,
ExecutableArguments = executableArguments ,
ProcessNameToMonitor = processToMonitor ,
ExecutableTimeout = timeout
2020-04-19 05:37:29 +00:00
} . ShowDialog ( ) ;
}
private static void CreateShortcutToSteamGame ( Profile profile , string steamGameIdToRun , uint timeout , string executableArguments )
{
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . User ;
2020-04-19 05:37:29 +00:00
new ShortcutForm ( profile )
2017-02-26 19:23:31 +00:00
{
2020-04-22 11:46:31 +00:00
GameLibrary = SupportedGameLibrary . Steam ,
GameAppId = Convert . ToUInt32 ( steamGameIdToRun ) ,
GameTimeout = timeout ,
GameArguments = executableArguments ,
2017-02-26 19:23:31 +00:00
} . ShowDialog ( ) ;
}
2020-04-19 05:37:29 +00:00
private static void CreateShortcutToUplayGame ( Profile profile , string uplayGameIdToRun , uint timeout , string executableArguments )
2017-02-26 19:23:31 +00:00
{
2020-04-19 05:37:29 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . User ;
new ShortcutForm ( profile )
2018-10-20 00:27:25 +00:00
{
2020-04-22 11:46:31 +00:00
GameLibrary = SupportedGameLibrary . Uplay ,
GameAppId = Convert . ToUInt32 ( uplayGameIdToRun ) ,
GameTimeout = timeout ,
GameArguments = executableArguments ,
2020-04-19 05:37:29 +00:00
} . ShowDialog ( ) ;
}
private static void EditProfile ( Profile profile )
{
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
// Get the status of the
2017-02-26 19:23:31 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . User ;
2020-04-19 05:37:29 +00:00
var editForm = new EditForm ( profile ) ;
2018-10-20 00:27:25 +00:00
2017-02-26 19:23:31 +00:00
if ( editForm . ShowDialog ( ) = = DialogResult . OK )
2018-10-20 00:27:25 +00:00
{
2020-04-19 05:37:29 +00:00
profile = editForm . Profile ;
2018-10-20 00:27:25 +00:00
}
2020-05-09 13:02:07 +00:00
var profiles = Profile . LoadAllProfiles ( ) . ToArray ( ) ;
if ( ! Profile . SaveAllProfiles ( ) )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
throw new Exception ( Language . Failed_to_save_profile ) ;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
}
2020-04-13 10:10:35 +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-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 ( "=" ) ;
Console . WriteLine ( @"Copyright <20> Terry MacDonald 2020-{DateTime.Today.Year}" ) ;
Console . WriteLine ( @"Based on Helios Display Management - Copyright <20> Soroush Falahati 2017-2020" ) ;
2020-04-27 10:55:44 +00:00
// Figure out where the shortcut's will go
2020-05-09 13:02:07 +00:00
ShortcutIconCachePath = Path . Combine ( AppDataPath , @"ShortcutIconCache" ) ;
// Create the Shortcut Icon Cache if it doesn't exist so that it's avilable for all the program
if ( ! Directory . Exists ( AppDataPath ) )
{
try
{
Directory . CreateDirectory ( ShortcutIconCachePath ) ;
}
catch
{
}
}
2020-04-27 10:55:44 +00:00
// Create the Shortcut Icon Cache if it doesn't exist so that it's avilable for all the program
if ( ! Directory . Exists ( ShortcutIconCachePath ) )
{
try
{
Directory . CreateDirectory ( ShortcutIconCachePath ) ;
}
catch
{
}
}
2020-04-19 05:37:29 +00:00
var app = new CommandLineApplication ( ) ;
2020-04-13 10:10:35 +00:00
2020-04-19 05:37:29 +00:00
//app.Name = "HeliosDM+";
//app.Name = Assembly.GetEntryAssembly().GetName().Name;
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
2020-04-19 05:37:29 +00:00
// This is the SwitchProfile command
2020-04-28 10:38:43 +00:00
app . Command ( "SwitchProfile" , ( switchProfileCmd ) = >
2020-04-14 10:18:52 +00:00
{
2020-04-19 05:37:29 +00:00
//description and help text of the command.
2020-04-28 10:38:43 +00:00
switchProfileCmd . Description = "Use this command to temporarily change profiles, and load your favourite game or application." ;
2018-10-20 00:27:25 +00:00
2020-04-28 10:38:43 +00:00
switchProfileCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
2020-04-28 10:38:43 +00:00
switchProfileCmd . ShowHelp ( ) ;
return 1 ;
} ) ;
2018-10-20 00:27:25 +00:00
2020-04-28 10:38:43 +00:00
switchProfileCmd . Command ( "permanent" , ( switchProfilePermanentSubCmd ) = >
{
switchProfilePermanentSubCmd . Description = "Change to a different display profile permanently (until you manually switch back)." ;
var optionProfile = switchProfilePermanentSubCmd . Option ( "-p|--profile <PROFILENAME>" , "(required) The Profile Name or Profile ID of the display profile to you want to use." , CommandOptionType . SingleValue ) . IsRequired ( ) ;
optionProfile . Validators . Add ( new ProfileMustExistValidator ( ) ) ;
switchProfilePermanentSubCmd . OnExecute ( ( ) = >
{
Console . WriteLine ( $"Changing to display profile {optionProfile.Value()}." ) ;
2020-04-19 05:37:29 +00:00
2020-04-28 10:38:43 +00:00
SwitchToProfile ( GetProfile ( optionProfile . Value ( ) ) ) ;
return 0 ;
} ) ;
2020-04-19 05:37:29 +00:00
} ) ;
2020-04-28 10:38:43 +00:00
switchProfileCmd . Command ( "exe" , ( switchProfileExecuteSubCmd ) = >
2020-04-14 10:18:52 +00:00
{
2020-04-28 10:38:43 +00:00
switchProfileExecuteSubCmd . Description = "Temporarily change to a different display profile, run an application or game executable, then change back." ;
var argumentExecutable = switchProfileExecuteSubCmd . Argument ( "PATH_TO_EXE" , "(required) The game exectuable file to run." ) . IsRequired ( ) ;
2020-04-19 05:37:29 +00:00
argumentExecutable . Validators . Add ( new FileArgumentMustExistValidator ( ) ) ;
2020-04-28 10:38:43 +00:00
var optionProfile = switchProfileExecuteSubCmd . Option ( "-p|--profile <PROFILENAME>" , "(required) The Profile Name or Profile ID of the display profile to you want to use." , CommandOptionType . SingleValue ) . IsRequired ( ) ;
optionProfile . Validators . Add ( new ProfileMustExistValidator ( ) ) ;
var optionWaitFor = switchProfileExecuteSubCmd . Option ( "-w|--waitfor <PROCESSNAME>" , "(optional) The application/game to start when we're temporarily switching profile and running the application/game. Also can be used when creating a shortcut. Cannot be used with --steam or --uplay options." , CommandOptionType . SingleValue ) ;
2020-04-19 05:37:29 +00:00
optionWaitFor . Validators . Add ( new FileOptionMustExistValidator ( ) ) ;
2020-04-28 10:38:43 +00:00
var optionTimeout = switchProfileExecuteSubCmd . Option < uint > ( "-t|--timeout" , "(optional) The time in seconds we should delay starting the application/game when we're temporarily switching profile and running the application/game." , CommandOptionType . SingleValue ) ;
var optionArguments = switchProfileExecuteSubCmd . Option ( "-a|--arguments" , "(optional) Extra arguments to pass to the application/game when we're temporarily switching profile and running the application/game." , CommandOptionType . SingleValue ) ;
switchProfileExecuteSubCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
2020-04-28 10:38:43 +00:00
Console . WriteLine ( $"Changing to display profile {optionProfile.Value()}, running executable {argumentExecutable.Value} then reverting back to this display profile when finished." ) ;
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
SwitchToExecutable (
GetProfile ( optionProfile . Value ( ) ) ,
2020-04-28 10:38:43 +00:00
//GetProfile(argProfile.Value),
2020-04-19 05:37:29 +00:00
argumentExecutable . Value ,
optionWaitFor . Value ( ) ,
Convert . ToUInt32 ( optionTimeout . Value ( ) ) ,
optionArguments . Value ( )
) ;
return 0 ;
} ) ;
} ) ;
2020-04-28 10:38:43 +00:00
switchProfileCmd . Command ( "steam" , ( switchProfileSteamSubCmd ) = >
2020-04-14 10:18:52 +00:00
{
2020-04-28 10:38:43 +00:00
switchProfileSteamSubCmd . Description = "Change to a display profile and run a Steam game, then swap back." ;
var argumentSteam = switchProfileSteamSubCmd . Argument ( "STEAM_GAME_ID" , "(required) The Steam Game ID." ) . IsRequired ( ) ;
2020-04-19 05:37:29 +00:00
argumentSteam . Validators . Add ( new SteamArgumentMustExistValidator ( ) ) ;
2020-04-28 10:38:43 +00:00
var optionProfile = switchProfileSteamSubCmd . Option ( "-p|--profile <PROFILENAME>" , "(required) The Profile Name or Profile ID of the display profile to you want to use." , CommandOptionType . SingleValue ) . IsRequired ( ) ;
optionProfile . Validators . Add ( new ProfileMustExistValidator ( ) ) ;
var optionTimeout = switchProfileSteamSubCmd . Option < uint > ( "-t|--timeout" , "(optional) The time in seconds we should delay starting the application/game when we're temporarily switching profile and running the application/game. " , CommandOptionType . SingleValue ) ;
var optionArguments = switchProfileSteamSubCmd . Option ( "-a|--arguments" , "(optional) Extra arguments to pass to the application/game when we're temporarily switching profile and running the application/game." , CommandOptionType . SingleValue ) ;
switchProfileSteamSubCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
2020-04-28 10:38:43 +00:00
Console . WriteLine ( $"Changing to display profile {optionProfile.Value()}, running Steam Game ID:{argumentSteam.Value} then reverting back to this display profile when finished." ) ;
2020-04-19 05:37:29 +00:00
SwitchToSteamGame (
GetProfile ( optionProfile . Value ( ) ) ,
2020-04-28 10:38:43 +00:00
//GetProfile(argProfile.Value),
2020-04-19 05:37:29 +00:00
argumentSteam . Value ,
Convert . ToUInt32 ( optionTimeout . Value ( ) ) ,
optionArguments . Value ( )
) ;
return 0 ;
} ) ;
} ) ;
2020-04-28 10:38:43 +00:00
switchProfileCmd . Command ( "uplay" , ( switchProfileUplaySubCmd ) = >
2020-04-14 10:18:52 +00:00
{
2020-04-28 10:38:43 +00:00
switchProfileUplaySubCmd . Description = "Change to a display profile and run a Uplay game." ;
var argumentUplay = switchProfileUplaySubCmd . Argument ( "UPLAY_GAME_ID" , "(required) The Uplay Game ID to run for when we're temporarily switching profile and running the Uplay application/game." ) . IsRequired ( ) ;
argumentUplay . Validators . Add ( new UplayArgumentMustExistValidator ( ) ) ;
var optionProfile = switchProfileUplaySubCmd . Option ( "-p|--profile <PROFILENAME>" , "(required) The Profile Name or Profile ID of the display profile to you want to use." , CommandOptionType . SingleValue ) . IsRequired ( ) ;
optionProfile . Validators . Add ( new ProfileMustExistValidator ( ) ) ;
var optionTimeout = switchProfileUplaySubCmd . Option < uint > ( "-t|--timeout" , "(optional) The time in seconds we should delay starting the application/game when we're temporarily switching profile and running the application/game." , CommandOptionType . SingleValue ) ;
var optionArguments = switchProfileUplaySubCmd . Option ( "-a|--arguments" , "(optional) Extra arguments to pass to the application/game when we're temporarily switching profile and running the application/game." , CommandOptionType . SingleValue ) ;
switchProfileUplaySubCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
2020-04-28 10:38:43 +00:00
Console . WriteLine ( $"Changing to display profile {optionProfile.Value()}, running Uplay Game ID:{argumentUplay.Value} then reverting back to this display profile when finished." ) ;
2020-04-19 05:37:29 +00:00
SwitchToUplayGame (
GetProfile ( optionProfile . Value ( ) ) ,
2020-04-28 10:38:43 +00:00
//GetProfile(argProfile.Value),
2020-04-19 05:37:29 +00:00
argumentUplay . Value ,
Convert . ToUInt32 ( optionTimeout . Value ( ) ) ,
optionArguments . Value ( )
) ;
return 0 ;
} ) ;
} ) ;
} ) ;
2020-04-28 10:38:43 +00:00
/ * // This is the CreateShortcut command
app . Command ( "CreateShortcut" , ( createShortcutCmd ) = >
2020-04-19 05:37:29 +00:00
{
//description and help text of the command.
2020-04-28 10:38:43 +00:00
createShortcutCmd . Description = "Use this command to create a new shortcut to your favourite game." ;
//createShortcutCmd.ExtendedHelpText = "Use this command to create a new shortcut to your favourite game.";
2020-04-19 05:37:29 +00:00
2020-04-28 10:38:43 +00:00
var optionProfile = createShortcutCmd . Option ( "-p|--profile" , "The Profile Name or Profile ID of the profile to you want to use." , CommandOptionType . SingleValue ) . IsRequired ( ) ;
optionProfile . Validators . Add ( new ProfileMustExistValidator ( ) ) ;
createShortcutCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
2020-04-28 10:38:43 +00:00
createShortcutCmd . ShowHelp ( ) ;
2020-04-19 05:37:29 +00:00
return 1 ;
} ) ;
2020-04-28 10:38:43 +00:00
createShortcutCmd . Command ( "exe" , ( createShortcutExecutableSubCmd ) = >
2020-04-14 10:18:52 +00:00
{
2020-04-28 10:38:43 +00:00
createShortcutExecutableSubCmd . Description = "Create a shortcut to run a Game executable." ;
var argumentExecutable = createShortcutExecutableSubCmd . Argument ( "executabletorun" , "The game exectuable file to run." ) . IsRequired ( ) ;
2020-04-19 05:37:29 +00:00
argumentExecutable . Validators . Add ( new FileArgumentMustExistValidator ( ) ) ;
2020-04-28 10:38:43 +00:00
var optionWaitFor = createShortcutExecutableSubCmd . Option ( "-w|--waitfor <PROCESSNAME>" , "(optional) The application/game to start when we're temporarily switching profile and running the application/game. Also can be used when creating a shortcut. Cannot be used with --steam or --uplay options." , CommandOptionType . SingleValue ) ;
2020-04-19 05:37:29 +00:00
optionWaitFor . Validators . Add ( new FileOptionMustExistValidator ( ) ) ;
2020-04-28 10:38:43 +00:00
var optionTimeout = createShortcutExecutableSubCmd . Option < uint > ( "-t|--timeout" , "(optional) The time in seconds we should delay starting the application/game when we're temporarily switching profile and running the application/game. Also can be used when creating a shortcut." , CommandOptionType . SingleValue ) ;
var optionArguments = createShortcutExecutableSubCmd . Option ( "-a|--arguments" , "(optional) Extra arguments to pass to the application/game when we're temporarily switching profile and running the application/game. Also can be used when creating a shortcut." , CommandOptionType . SingleValue ) ;
createShortcutExecutableSubCmd . OnExecute ( ( ) = >
2020-04-16 10:49:11 +00:00
{
2020-04-19 05:37:29 +00:00
Console . WriteLine ( $"Creating a Desktop Shortcut to the application or game {argumentExecutable.Value}" ) ;
CreateShortcutToExecutable (
GetProfile ( optionProfile . Value ( ) ) ,
argumentExecutable . Value ,
optionWaitFor . Value ( ) ,
Convert . ToUInt32 ( optionTimeout . Value ( ) ) ,
optionArguments . Value ( )
) ;
return 0 ;
} ) ;
} ) ;
2020-04-28 10:38:43 +00:00
createShortcutCmd . Command ( "steam" , ( createShortcutSteamSubCmd ) = >
2020-04-16 10:49:11 +00:00
{
2020-04-28 10:38:43 +00:00
createShortcutSteamSubCmd . Description = "Create a Steam Game shortcut." ;
var argumentSteam = createShortcutSteamSubCmd . Argument ( "steamgameid" , "The Steam Game ID." ) . IsRequired ( ) ;
2020-04-19 05:37:29 +00:00
argumentSteam . Validators . Add ( new SteamArgumentMustExistValidator ( ) ) ;
2020-04-28 10:38:43 +00:00
var optionTimeout = createShortcutSteamSubCmd . Option < uint > ( "-t|--timeout" , "(optional) The time in seconds we should delay starting the application/game when we're temporarily switching profile and running the application/game. Also can be used when creating a shortcut." , CommandOptionType . SingleValue ) ;
var optionArguments = createShortcutSteamSubCmd . Option ( "-a|--arguments" , "(optional) Extra arguments to pass to the application/game when we're temporarily switching profile and running the application/game. Also can be used when creating a shortcut." , CommandOptionType . SingleValue ) ;
createShortcutSteamSubCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
Console . WriteLine ( $"Creating a Desktop Shortcut to the Steam Game {argumentSteam.Value}" ) ;
2020-04-13 10:10:35 +00:00
2020-04-19 05:37:29 +00:00
CreateShortcutToSteamGame (
GetProfile ( optionProfile . Value ( ) ) ,
argumentSteam . Value ,
Convert . ToUInt32 ( optionTimeout . Value ( ) ) ,
optionArguments . Value ( )
) ;
2020-04-13 10:10:35 +00:00
2020-04-19 05:37:29 +00:00
return 0 ;
} ) ;
} ) ;
2020-04-28 10:38:43 +00:00
createShortcutCmd . Command ( "uplay" , ( createShortcutUplaySubCmd ) = >
2020-04-14 10:18:52 +00:00
{
2020-04-28 10:38:43 +00:00
createShortcutUplaySubCmd . Description = "Create a Uplay Game shortcut." ;
var argumentUplay = createShortcutUplaySubCmd . Argument ( "uplaygameid" , "The Uplay Game ID to run for when we're temporarily switching profile and running the Uplay application/game." ) . IsRequired ( ) ;
2020-04-19 05:37:29 +00:00
argumentUplay . Validators . Add ( new UplayArgumentMustExistValidator ( ) ) ;
2020-04-28 10:38:43 +00:00
var optionTimeout = createShortcutUplaySubCmd . Option < uint > ( "-t|--timeout" , "(optional) The time in seconds we should delay starting the application/game when we're temporarily switching profile and running the application/game. Also can be used when creating a shortcut." , CommandOptionType . SingleValue ) ;
var optionArguments = createShortcutUplaySubCmd . Option ( "-a|--arguments" , "(optional) Extra arguments to pass to the application/game when we're temporarily switching profile and running the application/game. Also can be used when creating a shortcut." , CommandOptionType . SingleValue ) ;
createShortcutUplaySubCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
Console . WriteLine ( $"Creating a Desktop Shortcut to the Uplay Game {argumentUplay.Value}" ) ;
2020-04-13 10:10:35 +00:00
2020-04-19 05:37:29 +00:00
CreateShortcutToUplayGame (
GetProfile ( optionProfile . Value ( ) ) ,
argumentUplay . Value ,
Convert . ToUInt32 ( optionTimeout . Value ( ) ) ,
optionArguments . Value ( )
) ;
2020-04-13 10:10:35 +00:00
2020-04-19 05:37:29 +00:00
return 0 ;
} ) ;
} ) ;
2020-04-13 10:10:35 +00:00
2020-04-28 10:38:43 +00:00
} ) ; * /
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
// This is the EditProfile command
2020-04-28 10:38:43 +00:00
app . Command ( "EditProfile" , ( editProfileCmd ) = >
2020-04-19 05:37:29 +00:00
{
//description and help text of the command.
2020-04-28 10:38:43 +00:00
editProfileCmd . Description = "Use this command to edit a HeliosDMPlus profile." ;
2020-04-19 05:37:29 +00:00
2020-04-28 10:38:43 +00:00
var optionProfile = editProfileCmd . Option ( "-p|--profile" , "The Profile Name or Profile ID of the profile to you want to use." , CommandOptionType . SingleValue ) . IsRequired ( ) ;
optionProfile . Validators . Add ( new ProfileMustExistValidator ( ) ) ;
editProfileCmd . OnExecute ( ( ) = >
2020-04-19 05:37:29 +00:00
{
Console . WriteLine ( $"Editing profile {optionProfile.Value()}" ) ;
EditProfile (
GetProfile ( optionProfile . Value ( ) )
) ;
return 0 ;
} ) ;
} ) ;
2020-04-22 11:46:31 +00:00
app . OnExecute ( ( ) = >
{
Console . WriteLine ( "Starting Normally..." ) ;
StartUpNormally ( ) ;
return 0 ;
} ) ;
2020-04-19 05:37:29 +00:00
try
{
// This begins the actual execution of the application
app . Execute ( args ) ;
}
catch ( CommandParsingException ex )
{
// 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>'"
Console . WriteLine ( ex . Message ) ;
}
catch ( Exception ex )
{
Console . WriteLine ( "Unable to execute application: {0}" , ex . Message ) ;
}
return 0 ;
//return app.Execute(args);
}
private static void StartUpNormally ( )
{
Application . EnableVisualStyles ( ) ;
Application . SetCompatibleTextRenderingDefault ( false ) ;
ServicePointManager . SecurityProtocol = SecurityProtocolType . Tls12 ;
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-04-19 05:37:29 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . User ;
2020-05-03 08:39:35 +00:00
Application . Run ( new UIForms . MainForm ( ) ) ;
2020-04-19 05:37:29 +00:00
2020-04-14 10:18:52 +00:00
}
catch ( Exception e )
{
MessageBox . Show (
string . Format ( Language . Operation_Failed , e . Message ) ,
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
2020-04-19 05:37:29 +00:00
private static void SwitchToExecutable ( Profile profile , string executableToRun , string processToMonitor , uint timeout , string executableArguments )
2017-02-26 19:23:31 +00:00
{
2020-05-09 13:02:07 +00:00
var rollbackProfile = Profile . CurrentProfile ;
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
if ( ! profile . IsPossible )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
throw new Exception ( Language . Selected_profile_is_not_possible ) ;
2018-10-20 00:27:25 +00:00
}
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-04-19 05:37:29 +00:00
if ( ! GoProfile ( profile ) )
2017-02-26 19:23:31 +00:00
{
2020-04-19 05:37:29 +00:00
throw new Exception ( Language . Can_not_change_active_profile ) ;
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
var process = System . Diagnostics . Process . Start ( executableToRun , executableArguments ) ;
var processes = new System . Diagnostics . Process [ 0 ] ;
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
var ticks = 0 ;
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
while ( ticks < timeout * 1000 )
{
processes = System . Diagnostics . Process . GetProcessesByName ( processToMonitor ) ;
if ( processes . Length > 0 )
2017-02-26 19:23:31 +00:00
{
2020-04-19 05:37:29 +00:00
break ;
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
Thread . Sleep ( 300 ) ;
ticks + = 300 ;
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
if ( processes . Length = = 0 )
{
processes = new [ ] { process } ;
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
IPCService . GetInstance ( ) . HoldProcessId = processes . FirstOrDefault ( ) ? . Id ? ? 0 ;
IPCService . GetInstance ( ) . Status = InstanceStatus . OnHold ;
NotifyIcon notify = null ;
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
try
{
notify = new NotifyIcon
{
2020-05-09 13:02:07 +00:00
Icon = Properties . Resources . HeliosPlus ,
2020-04-19 05:37:29 +00:00
Text = string . Format (
Language . Waiting_for_the_0_to_terminate ,
processes [ 0 ] . ProcessName ) ,
Visible = true
} ;
Application . DoEvents ( ) ;
}
catch
{
// ignored
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
foreach ( var p in processes )
{
2017-08-10 14:12:44 +00:00
try
{
2020-04-19 05:37:29 +00:00
p . WaitForExit ( ) ;
2017-08-10 14:12:44 +00:00
}
catch
{
// ignored
}
2020-04-19 05:37:29 +00:00
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
if ( notify ! = null )
{
notify . Visible = false ;
notify . Dispose ( ) ;
Application . DoEvents ( ) ;
}
IPCService . GetInstance ( ) . Status = InstanceStatus . Busy ;
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
if ( ! rollbackProfile . IsActive )
{
if ( ! GoProfile ( rollbackProfile ) )
2017-08-10 14:12:44 +00:00
{
2020-04-19 05:37:29 +00:00
throw new Exception ( Language . Can_not_change_active_profile ) ;
2017-08-10 14:12:44 +00:00
}
2020-04-19 05:37:29 +00:00
}
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
private static void SwitchToSteamGame ( Profile profile , string steamGameIdToRun , uint timeout , string steamGameArguments )
{
2020-04-27 10:55:44 +00:00
// Convert the steamGameIdToRun string to a uint for Steam Games
uint steamGameIdUint = 0 ;
if ( ! uint . TryParse ( steamGameIdToRun , out steamGameIdUint ) )
{
throw new Exception ( "ERROR - Couldn't convert the string steamGameIdToRun parameter to steamGameIdUint in SwitchToSteamGame!" ) ;
}
2020-04-29 10:29:43 +00:00
// Save the profile we're on now
2020-05-09 13:02:07 +00:00
var rollbackProfile = Profile . CurrentProfile ;
2020-04-19 05:37:29 +00:00
2020-04-29 10:29:43 +00:00
// Check that the profile we've been asked to change to will actually work
2020-04-19 05:37:29 +00:00
if ( ! profile . IsPossible )
{
throw new Exception ( Language . Selected_profile_is_not_possible ) ;
2017-02-26 19:23:31 +00:00
}
2020-04-19 05:37:29 +00:00
2020-04-29 10:29:43 +00:00
//
if ( IPCClient . QueryAll ( ) . Any (
2020-04-19 05:37:29 +00:00
client = >
client . Status = = InstanceStatus . Busy | |
client . Status = = InstanceStatus . OnHold ) )
2017-02-26 19:23:31 +00:00
{
2020-04-19 05:37:29 +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-04-29 10:29:43 +00:00
// Create the SteamGame objects so we can use them shortly
// Get the game information relevant to the game we're switching to
2020-04-27 10:55:44 +00:00
List < SteamGame > allSteamGames = SteamGame . GetAllInstalledGames ( ) ;
2018-10-20 00:27:25 +00:00
2020-04-29 10:29:43 +00:00
// Check if Steam is installed and error if it isn't
if ( ! SteamGame . SteamInstalled )
{
throw new Exception ( Language . Steam_is_not_installed ) ;
}
// Otherwise try to find the game we've been asked to run
2020-04-27 10:55:44 +00:00
SteamGame steamGameToRun = null ;
foreach ( SteamGame steamGameToCheck in allSteamGames )
2020-04-19 05:37:29 +00:00
{
2020-04-27 10:55:44 +00:00
if ( steamGameToCheck . GameId = = steamGameIdUint )
{
steamGameToRun = steamGameToCheck ;
break ;
}
2020-04-19 05:37:29 +00:00
}
2020-04-29 10:29:43 +00:00
// Attempt to change to a different profile if it's needed
2020-04-19 05:37:29 +00:00
if ( ! GoProfile ( profile ) )
{
throw new Exception ( Language . Can_not_change_active_profile ) ;
}
2020-04-29 10:29:43 +00:00
// Prepare to start the steam game using the URI interface
// as used by Steam for it's own desktop shortcuts.
2020-04-27 10:55:44 +00:00
var address = $"steam://rungameid/{steamGameToRun.GameId}" ;
2020-04-19 05:37:29 +00:00
if ( ! string . IsNullOrWhiteSpace ( steamGameArguments ) )
{
address + = "/" + steamGameArguments ;
}
2020-04-29 10:29:43 +00:00
2020-04-19 05:37:29 +00:00
var steamProcess = System . Diagnostics . Process . Start ( address ) ;
// Wait for steam game to update and then run
var ticks = 0 ;
while ( ticks < timeout * 1000 )
{
2020-04-27 10:55:44 +00:00
if ( steamGameToRun . IsRunning )
2018-10-20 00:27:25 +00:00
{
2020-04-19 05:37:29 +00:00
break ;
2018-10-20 00:27:25 +00:00
}
2020-04-19 05:37:29 +00:00
Thread . Sleep ( 300 ) ;
2018-10-20 00:27:25 +00:00
2020-04-27 10:55:44 +00:00
if ( ! steamGameToRun . IsUpdating )
2018-10-20 00:27:25 +00:00
{
2020-04-19 05:37:29 +00:00
ticks + = 300 ;
2018-10-20 00:27:25 +00:00
}
2020-04-19 05:37:29 +00:00
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
IPCService . GetInstance ( ) . HoldProcessId = steamProcess ? . Id ? ? 0 ;
IPCService . GetInstance ( ) . Status = InstanceStatus . OnHold ;
NotifyIcon notify = null ;
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
try
{
notify = new NotifyIcon
2017-02-26 19:23:31 +00:00
{
2020-05-09 13:02:07 +00:00
Icon = Properties . Resources . HeliosPlus ,
2020-04-19 05:37:29 +00:00
Text = string . Format (
Language . Waiting_for_the_0_to_terminate ,
2020-04-27 10:55:44 +00:00
steamGameToRun . GameName ) ,
2020-04-19 05:37:29 +00:00
Visible = true
} ;
Application . DoEvents ( ) ;
}
catch
{
// ignored
}
// Wait for the game to exit
2020-04-27 10:55:44 +00:00
if ( steamGameToRun . IsRunning )
2020-04-19 05:37:29 +00:00
{
while ( true )
{
2020-04-27 10:55:44 +00:00
if ( ! steamGameToRun . IsRunning )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
break ;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
Thread . Sleep ( 300 ) ;
}
2020-04-19 05:37:29 +00:00
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
if ( notify ! = null )
{
notify . Visible = false ;
notify . Dispose ( ) ;
Application . DoEvents ( ) ;
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . Busy ;
if ( ! rollbackProfile . IsActive )
{
if ( ! GoProfile ( rollbackProfile ) )
2017-08-10 14:12:44 +00:00
{
2020-04-19 05:37:29 +00:00
throw new Exception ( Language . Can_not_change_active_profile ) ;
2017-08-10 14:12:44 +00:00
}
2020-04-19 05:37:29 +00:00
}
}
private static void SwitchToUplayGame ( Profile profile , string uplayGameIdToRun , uint timeout , string uplayGameArguments )
{
2020-05-09 13:02:07 +00:00
var rollbackProfile = Profile . CurrentProfile ;
2020-04-19 05:37:29 +00:00
if ( ! profile . IsPossible )
{
throw new Exception ( Language . Selected_profile_is_not_possible ) ;
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
if (
IPCClient . QueryAll ( )
. Any (
client = >
client . Status = = InstanceStatus . Busy | |
client . Status = = InstanceStatus . OnHold ) )
{
throw new Exception (
Language
. Another_instance_of_this_program_is_in_working_state_Please_close_other_instances_before_trying_to_switch_profile ) ;
}
2020-04-27 10:55:44 +00:00
/ * var steamGame = new SteamGame ( Convert . ToUInt32 ( uplayGameIdToRun ) ) ;
2020-04-19 05:37:29 +00:00
if ( ! SteamGame . SteamInstalled )
{
throw new Exception ( Language . Steam_is_not_installed ) ;
}
2020-04-27 10:55:44 +00:00
if ( ! File . Exists ( SteamGame . SteamExe ) )
2020-04-19 05:37:29 +00:00
{
throw new Exception ( Language . Steam_executable_file_not_found ) ;
}
if ( ! steamGame . IsInstalled )
{
throw new Exception ( Language . Steam_game_is_not_installed ) ;
}
if ( ! GoProfile ( profile ) )
{
throw new Exception ( Language . Can_not_change_active_profile ) ;
}
var address = $"uplay://rungameid/{steamGame.AppId}" ;
if ( ! string . IsNullOrWhiteSpace ( uplayGameArguments ) )
{
address + = "/" + uplayGameArguments ;
}
var steamProcess = System . Diagnostics . Process . Start ( address ) ;
// Wait for steam game to update and then run
var ticks = 0 ;
while ( ticks < timeout * 1000 )
{
2017-02-26 19:23:31 +00:00
if ( steamGame . IsRunning )
2018-10-20 00:27:25 +00:00
{
2020-04-19 05:37:29 +00:00
break ;
2018-10-20 00:27:25 +00:00
}
2020-04-19 05:37:29 +00:00
Thread . Sleep ( 300 ) ;
if ( ! steamGame . IsUpdating )
2017-08-10 14:12:44 +00:00
{
2020-04-19 05:37:29 +00:00
ticks + = 300 ;
2017-08-10 14:12:44 +00:00
}
2020-04-19 05:37:29 +00:00
}
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
IPCService . GetInstance ( ) . HoldProcessId = steamProcess ? . Id ? ? 0 ;
IPCService . GetInstance ( ) . Status = InstanceStatus . OnHold ;
NotifyIcon notify = null ;
2018-10-20 00:27:25 +00:00
2020-04-19 05:37:29 +00:00
try
{
notify = new NotifyIcon
{
Icon = Properties . Resources . Icon ,
Text = string . Format (
Language . Waiting_for_the_0_to_terminate ,
steamGame . Name ) ,
Visible = true
} ;
Application . DoEvents ( ) ;
}
catch
{
// ignored
}
// Wait for the game to exit
if ( steamGame . IsRunning )
{
while ( true )
2018-10-20 00:27:25 +00:00
{
2020-04-19 05:37:29 +00:00
if ( ! steamGame . IsRunning )
2018-10-20 00:27:25 +00:00
{
2020-04-19 05:37:29 +00:00
break ;
2018-10-20 00:27:25 +00:00
}
2020-04-19 05:37:29 +00:00
Thread . Sleep ( 300 ) ;
2018-10-20 00:27:25 +00:00
}
2017-02-26 19:23:31 +00:00
}
2020-04-19 05:37:29 +00:00
if ( notify ! = null )
{
notify . Visible = false ;
notify . Dispose ( ) ;
Application . DoEvents ( ) ;
}
IPCService . GetInstance ( ) . Status = InstanceStatus . Busy ;
if ( ! rollbackProfile . IsActive )
2017-02-26 19:23:31 +00:00
{
2020-04-19 05:37:29 +00:00
if ( ! GoProfile ( rollbackProfile ) )
2018-10-20 00:27:25 +00:00
{
2017-02-26 19:23:31 +00:00
throw new Exception ( Language . Can_not_change_active_profile ) ;
2018-10-20 00:27:25 +00:00
}
2020-04-27 10:55:44 +00:00
} * /
2020-04-19 05:37:29 +00:00
}
// ReSharper disable once CyclomaticComplexity
private static void SwitchToProfile ( Profile profile )
{
2020-05-09 13:02:07 +00:00
var rollbackProfile = Profile . CurrentProfile ;
2020-04-19 05:37:29 +00:00
if (
IPCClient . QueryAll ( )
. Any (
client = >
client . Status = = InstanceStatus . Busy | |
client . Status = = InstanceStatus . OnHold ) )
{
throw new Exception (
Language
. Another_instance_of_this_program_is_in_working_state_Please_close_other_instances_before_trying_to_switch_profile ) ;
}
if ( ! GoProfile ( profile ) )
{
throw new Exception ( Language . Can_not_change_active_profile ) ;
}
2017-02-26 19:23:31 +00:00
}
}
}