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 ;
2020-05-17 09:19:55 +00:00
using System.Text.RegularExpressions ;
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
2020-05-15 08:52:16 +00:00
if ( new ApplyingChangesForm ( ( ) = >
2017-02-26 19:23:31 +00:00
{
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 EditProfile ( Profile profile )
{
2020-05-15 11:08:44 +00:00
// Get the status of the thing
2017-02-26 19:23:31 +00:00
IPCService . GetInstance ( ) . Status = InstanceStatus . User ;
2020-05-15 11:08:44 +00:00
// Load all the profiles from JSON
Profile . LoadAllProfiles ( ) . ToArray ( ) ;
// Start up the DisplayProfileForm directly
new DisplayProfileForm ( profile ) . ShowDialog ( ) ;
// Then we close down as we're only here to edit one profile
Application . Exit ( ) ;
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-05-17 09:19:55 +00:00
app . Command ( "RunShortcut" , ( switchProfileCmd ) = >
2020-04-14 10:18:52 +00:00
{
2020-05-17 09:19:55 +00:00
var argumentShortcut = switchProfileCmd . Argument ( "\"SHORTCUT_NAME\"" , "(required) The name of the shortcut to run from those stored in the shortcut library." ) . IsRequired ( ) ;
argumentShortcut . Validators . Add ( new ShortcutMustExistValidator ( ) ) ;
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-05-17 09:19:55 +00:00
Console . WriteLine ( $"Editing profile {argumentShortcut.Value}" ) ;
2020-04-19 05:37:29 +00:00
2020-05-17 09:19:55 +00:00
SwitchToProfile ( GetProfile ( argumentShortcut . Value ) ) ;
2020-04-19 05:37:29 +00:00
2020-05-17 09:19:55 +00:00
return 0 ;
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
}
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 ;
}
public static string GetValidFilename ( string uncheckedFilename )
{
string invalid = new string ( Path . GetInvalidFileNameChars ( ) ) + new string ( Path . GetInvalidPathChars ( ) ) ;
foreach ( char c in invalid )
{
uncheckedFilename = uncheckedFilename . Replace ( c . ToString ( ) , "" ) ;
}
return uncheckedFilename ;
}
2017-02-26 19:23:31 +00:00
}
}