2022-12-11 02:35:46 +01:00
using System.ComponentModel ;
using System.Diagnostics ;
using System.Reflection ;
2022-12-12 18:47:54 +01:00
using System.Web ;
2022-12-11 02:35:46 +01:00
using AutoUpdaterDotNET ;
using CommonHelpers ;
namespace Updater
{
internal static class Program
{
public const String Title = "Steam Deck Tools" ;
public const String RunPrefix = "-run=" ;
public const String UpdatedArg = "-updated" ;
2022-12-14 11:34:11 +01:00
public const String UPDATER_SENTRY_DSN = "https://a41ee1b3a3294d38887e6f43627f5853@o4504326877216768.ingest.sentry.io/4504326879641600" ;
2022-12-11 02:35:46 +01:00
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main ( )
2022-12-12 15:08:00 +01:00
{
Instance . WithSentry ( ( ) = >
{
Run ( ) ;
2022-12-14 11:34:11 +01:00
} , UPDATER_SENTRY_DSN ) ;
2022-12-12 15:08:00 +01:00
}
static void Run ( )
2022-12-11 02:35:46 +01:00
{
bool firstRun = Environment . GetCommandLineArgs ( ) . Contains ( "-first" ) ;
bool userCheck = Environment . GetCommandLineArgs ( ) . Contains ( "-user" ) ;
bool updated = Environment . GetCommandLineArgs ( ) . Contains ( UpdatedArg ) ;
bool cmdLine = ! firstRun & & ! userCheck ;
2022-12-11 13:26:46 +01:00
Instance . OnUninstall ( ( ) = >
{
2022-12-11 15:02:31 +01:00
KillApps ( ) ;
2022-12-11 13:26:46 +01:00
} ) ;
2022-12-11 02:35:46 +01:00
if ( updated )
{
foreach ( var arg in Environment . GetCommandLineArgs ( ) )
{
if ( ! arg . StartsWith ( RunPrefix ) )
continue ;
var processName = arg . Substring ( RunPrefix . Length ) ;
CommonHelpers . Log . TraceLine ( "Running {0}" , processName ) ;
try { Process . Start ( processName ) ; } catch { }
}
return ;
}
Instance . RunOnce ( null , "Global\\SteamDeckToolsAutoUpdater" ) ;
2022-12-16 22:32:59 +01:00
if ( File . Exists ( "DisableCheckForUpdates.txt" ) )
{
if ( userCheck | | cmdLine )
{
MessageBox . Show (
"This application has explicitly disabled auto-updates. Remove the 'DisableCheckForUpdates.txt' file and retry again" ,
Title ,
MessageBoxButtons . OK
) ;
}
return ;
}
2022-12-11 02:35:46 +01:00
var persistence = new RegistryPersistenceProvider ( @"Software\SteamDeckTools\AutoUpdater" ) ;
if ( userCheck | | cmdLine )
{
persistence . SetRemindLater ( null ) ;
persistence . SetSkippedVersion ( new Version ( ) ) ;
}
AutoUpdater . AppTitle = Title ;
AutoUpdater . RemindLaterTimeSpan = RemindLaterFormat . Days ;
AutoUpdater . LetUserSelectRemindLater = true ;
AutoUpdater . ShowRemindLaterButton = true ;
2022-12-16 10:05:35 +01:00
AutoUpdater . HttpUserAgent = String . Format ( "AutoUpdater/{0}/{1}/{2}" ,
2022-12-17 21:37:34 +01:00
Instance . ID ,
2022-12-16 10:05:35 +01:00
Instance . ProductVersionWithSha ,
Instance . IsProductionBuild ? "prod" : "dev" ) ;
2022-12-11 02:35:46 +01:00
AutoUpdater . PersistenceProvider = persistence ;
AutoUpdater . ReportErrors = userCheck | | cmdLine ;
AutoUpdater . UpdateFormSize = new Size ( 800 , 300 ) ;
AutoUpdater . ShowSkipButton = true ;
AutoUpdater . Synchronous = true ;
2022-12-11 15:02:31 +01:00
if ( ! IsUsingInstaller )
{
// Only when not using installer we have to kill apps
AutoUpdater . ApplicationExitEvent + = KillApps ;
}
2022-12-11 02:35:46 +01:00
AppendArg ( UpdatedArg ) ;
2022-12-18 09:57:05 +01:00
List < string > usedTools = new List < string > ( ) ;
TrackProcess ( "FanControl" , usedTools ) ;
TrackProcess ( "PowerControl" , usedTools ) ;
TrackProcess ( "PerformanceOverlay" , usedTools ) ;
TrackProcess ( "SteamController" , usedTools ) ;
2022-12-11 02:35:46 +01:00
2022-12-11 13:26:46 +01:00
var updateURL = String . Format (
2022-12-18 09:57:05 +01:00
"https://steam-deck-tools.ayufan.dev/docs/updates/{0}_{1}.xml?version={2}&id={3}&env={4}&apps={5}" ,
2022-12-11 13:26:46 +01:00
Instance . IsDEBUG ? "debug" : "release" ,
IsUsingInstaller ? "setup" : "zip" ,
2022-12-16 10:05:35 +01:00
HttpUtility . UrlEncode ( Instance . ProductVersionWithSha ) ,
2022-12-17 21:37:34 +01:00
HttpUtility . UrlEncode ( Instance . ID ) ,
2022-12-18 09:57:05 +01:00
Instance . IsProductionBuild ? "prod" : "dev" ,
HttpUtility . UrlEncode ( String . Join ( "," , usedTools ) )
2022-12-11 13:26:46 +01:00
) ;
AutoUpdater . Start ( updateURL ) ;
2022-12-11 02:35:46 +01:00
}
2022-12-18 09:57:05 +01:00
private static bool TrackProcess ( String processFilterName , List < string > ? usedTools = null )
2022-12-11 02:35:46 +01:00
{
2022-12-18 09:57:05 +01:00
if ( FindProcesses ( processFilterName ) . Any ( ) )
{
AppendArg ( RunPrefix + processFilterName ) ;
usedTools ? . Add ( processFilterName ) ;
return true ;
}
return false ;
2022-12-11 02:35:46 +01:00
}
2022-12-11 15:02:31 +01:00
private static void KillApps ( )
2022-12-11 02:35:46 +01:00
{
ExitProcess ( "FanControl" ) ;
ExitProcess ( "PowerControl" ) ;
ExitProcess ( "PerformanceOverlay" ) ;
ExitProcess ( "SteamController" ) ;
ExitProcess ( "Updater" ) ;
}
private static void AppendArg ( string arg )
{
var setCommandLineArgs = typeof ( Environment ) . GetMethod (
"SetCommandLineArgs" , BindingFlags . Static | BindingFlags . NonPublic ,
new Type [ ] { typeof ( string [ ] ) } ) ;
if ( setCommandLineArgs is null )
return ;
// append `-run:<process>` to command line args
setCommandLineArgs . Invoke ( null , new object [ ] {
Environment . GetCommandLineArgs ( ) . Append ( arg ) . ToArray ( )
} ) ;
}
private static bool ExitProcess ( String processFilerName )
{
bool found = false ;
foreach ( var process in FindProcesses ( processFilerName ) )
{
if ( process . CloseMainWindow ( ) )
{
process . WaitForExit ( ( int ) TimeSpan . FromSeconds ( 10 )
. TotalMilliseconds ) ; //give some time to process message
}
if ( ! process . HasExited )
{
process . Kill ( ) ; //TODO show UI message asking user to close program himself instead of silently killing it
}
found = true ;
}
return found ;
}
2022-12-11 13:26:46 +01:00
private static bool IsUsingInstaller
{
get
{
var currentProcess = Process . GetCurrentProcess ( ) ;
var currentDir = Path . GetDirectoryName ( currentProcess . MainModule ? . FileName ) ;
if ( currentDir is null )
return false ;
var uninstallExe = Path . Combine ( currentDir , "Uninstall.exe" ) ;
return File . Exists ( uninstallExe ) ;
}
}
2022-12-11 02:35:46 +01:00
private static IEnumerable < Process > FindProcesses ( String processFilerName )
{
var currentProcess = Process . GetCurrentProcess ( ) ;
var currentDir = Path . GetDirectoryName ( currentProcess . MainModule ? . FileName ) ;
foreach ( var process in Process . GetProcessesByName ( processFilerName ) )
{
string? processFileName , processDir ;
try
{
processFileName = process . MainModule ? . FileName ;
if ( processFileName is null )
continue ;
processDir = Path . GetDirectoryName ( processFileName ) ;
}
catch ( Win32Exception )
{
// Current process should be same as processes created by other instances of the application so it should be able to access modules of other instances.
// This means this is not the process we are looking for so we can safely skip this.
continue ;
}
//get all instances of assembly except current
if ( process . Id ! = currentProcess . Id & & currentDir = = processDir )
{
yield return process ;
}
}
}
}
}