From 54354fe9e9c526ec66cae50004261203a2610603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Trzci=C5=84ski?= Date: Thu, 15 Dec 2022 21:28:14 +0100 Subject: [PATCH] Validate that all dependencies are installed --- CommonHelpers/Dependencies.cs | 137 +++++++++++++++++++++++++++++++ PerformanceOverlay/Controller.cs | 8 +- PowerControl/Controller.cs | 8 +- RELEASE.md | 1 + SteamController/Controller.cs | 7 +- 5 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 CommonHelpers/Dependencies.cs diff --git a/CommonHelpers/Dependencies.cs b/CommonHelpers/Dependencies.cs new file mode 100644 index 0000000..3368268 --- /dev/null +++ b/CommonHelpers/Dependencies.cs @@ -0,0 +1,137 @@ +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace CommonHelpers +{ + public static class Dependencies + { + public static string[] Hidapi = new string[] + { + "hidapi.dll" + }; + + public static string[] RTSSShared = new string[] + { + "RTSSSharedMemoryNET.dll" + }; + + private static string[] VCRuntime = new string[] + { + "vcruntime140.dll" + }; + + private static string[] RTSS = new string[] + { + "C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll" + }; + + private static string VCRuntimeURL = "https://aka.ms/vs/17/release/vc_redist.x64.exe"; + private static string RTSSURL = "https://www.guru3d.com/files-details/rtss-rivatuner-statistics-server-download.html"; + + public static void ValidateHidapi(string title) + { + ValidateVCRuntime(title); + ValidateDependency(title, "HidAPI", Hidapi, false); + } + + public static void ValidateRTSSSharedMemoryNET(string title) + { + ValidateVCRuntime(title); + ValidateDependency(title, "RTSSSharedMemoryNET", RTSSShared, false); + } + + public static void ValidateRTSS(string title) + { + InstallDependency(title, "Rivatuner Statistics Server", RTSS, RTSSURL, false, false); + } + + private static void ValidateVCRuntime(string title) + { + InstallDependency(title, "Microsoft Visual C++ Runtime", VCRuntime, VCRuntimeURL, true, false); + } + + private static void ValidateDependency(string title, string name, string[] dllNames, bool unload = true) + { + if (TryToLoad(dllNames, unload)) + return; + + Log.TraceError("Cannot load: {0}", dllNames); + + MessageBox.Show( + "Cannot load: " + string.Join(", ", dllNames) + ".\n\n" + + "Application will exit.\n", + title, + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + + Environment.Exit(1); + } + + private static void InstallDependency(string title, string name, string[] dllNames, string url, bool required = true, bool unload = true) + { + if (TryToLoad(dllNames, unload)) + return; + + Log.TraceError("Cannot load: {0}", dllNames); + + var result = MessageBox.Show( + "Missing '" + name + "' (" + string.Join(", ", dllNames) + ").\n\n" + + "Click Yes to download and install?\n", + title, + MessageBoxButtons.YesNo, + MessageBoxIcon.Error + ); + + if (result == DialogResult.Yes) + { + ExecuteLink(url); + Environment.Exit(1); + } + + if (required) + { + MessageBox.Show( + "The '" + name + "' is required. " + + "Application will exit now. " + + "Once installed start application again.", + title, + MessageBoxButtons.OK, + MessageBoxIcon.Error + ); + Environment.Exit(1); + } + } + + private static bool TryToLoad(string[] dllNames, bool unload = true) + { + foreach (var dllName in dllNames) + { + if (!TryToLoad(dllName, unload)) + return false; + } + return true; + } + + private static bool TryToLoad(string dllName, bool unload = true) + { + var handle = LoadLibrary(dllName); + if (unload) + FreeLibrary(handle); + return handle != IntPtr.Zero; + } + + private static void ExecuteLink(string link) + { + try { Process.Start("explorer.exe", link); } + catch { } + } + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr LoadLibrary(string lpFileName); + + [DllImport("kernel32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool FreeLibrary(IntPtr module); + } +} diff --git a/PerformanceOverlay/Controller.cs b/PerformanceOverlay/Controller.cs index 88c4afb..a1b9a68 100644 --- a/PerformanceOverlay/Controller.cs +++ b/PerformanceOverlay/Controller.cs @@ -8,7 +8,7 @@ namespace PerformanceOverlay internal class Controller : IDisposable { public const String Title = "Performance Overlay"; - public readonly String TitleWithVersion = Title + " v" + System.Windows.Forms.Application.ProductVersion.ToString(); + public static readonly String TitleWithVersion = Title + " v" + System.Windows.Forms.Application.ProductVersion.ToString(); Container components = new Container(); RTSSSharedMemoryNET.OSD? osd; @@ -24,6 +24,12 @@ namespace PerformanceOverlay SharedData sharedData = SharedData.CreateNew(); + static Controller() + { + Dependencies.ValidateRTSS(TitleWithVersion); + Dependencies.ValidateRTSSSharedMemoryNET(TitleWithVersion); + } + public Controller() { Instance.OnUninstall(() => diff --git a/PowerControl/Controller.cs b/PowerControl/Controller.cs index 8de5b35..0f56ce2 100644 --- a/PowerControl/Controller.cs +++ b/PowerControl/Controller.cs @@ -19,7 +19,7 @@ namespace PowerControl internal class Controller : IDisposable { public const String Title = "Power Control"; - public readonly String TitleWithVersion = Title + " v" + Application.ProductVersion.ToString(); + public static readonly String TitleWithVersion = Title + " v" + Application.ProductVersion.ToString(); public const int KeyPressRepeatTime = 400; public const int KeyPressNextRepeatTime = 90; @@ -38,6 +38,12 @@ namespace PowerControl SharedData sharedData = SharedData.CreateNew(); + static Controller() + { + Dependencies.ValidateHidapi(TitleWithVersion); + Dependencies.ValidateRTSSSharedMemoryNET(TitleWithVersion); + } + public Controller() { Instance.OnUninstall(() => diff --git a/RELEASE.md b/RELEASE.md index eff527d..f84ae74 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -15,3 +15,4 @@ - Add `Setup.exe` installer to install all except RTSS - Add `Sentry` error tracking - Use `white` icons when using `Dark Theme` (thanks @maniman303 https://github.com/ayufan/steam-deck-tools/pull/23) +- Validate that all dependencies are installed diff --git a/SteamController/Controller.cs b/SteamController/Controller.cs index eedb07e..93484b0 100644 --- a/SteamController/Controller.cs +++ b/SteamController/Controller.cs @@ -8,7 +8,7 @@ namespace SteamController internal class Controller : IDisposable { public const String Title = "Steam Controller"; - public readonly String TitleWithVersion = Title + " v" + Application.ProductVersion.ToString(); + public static readonly String TitleWithVersion = Title + " v" + Application.ProductVersion.ToString(); Container components = new Container(); NotifyIcon notifyIcon; @@ -32,6 +32,11 @@ namespace SteamController } }; + static Controller() + { + Dependencies.ValidateHidapi(TitleWithVersion); + } + public Controller() { Instance.OnUninstall(() =>