From 40f5f9b42365899e5ec5b64a94560f10446fabaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 30 Mar 2026 10:15:31 +0200 Subject: [PATCH 1/6] Updated resources for v3 release --- ControlApp/Views/Pages/DevicesPage.xaml | 4 +- README.md | 4 +- ...og.xaml => OnlineDocumentationDialog.xaml} | 10 ++--- ...l.cs => OnlineDocumentationDialog.xaml.cs} | 44 +++++-------------- setup/InstallScript.cs | 20 ++++----- 5 files changed, 29 insertions(+), 53 deletions(-) rename setup/Dialogs/{BetaArticleDialog.xaml => OnlineDocumentationDialog.xaml} (92%) rename setup/Dialogs/{BetaArticleDialog.xaml.cs => OnlineDocumentationDialog.xaml.cs} (50%) diff --git a/ControlApp/Views/Pages/DevicesPage.xaml b/ControlApp/Views/Pages/DevicesPage.xaml index cfc8381a3..87b9ec220 100644 --- a/ControlApp/Views/Pages/DevicesPage.xaml +++ b/ControlApp/Views/Pages/DevicesPage.xaml @@ -1,4 +1,4 @@ - + NavigateUri="https://docs.nefarius.at/projects/DsHidMini/v3/How-to-Install/#troubleshooting"> diff --git a/README.md b/README.md index 31bfe3a79..f9a9957bd 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ Virtual HID Mini user-mode driver for Sony DualShock 3 controllers on Windows 10/11. -## Version 3 (Beta) +## Version 3 (Stable) -The next major version is [available for Beta-testing](https://github.com/nefarius/DsHidMini/releases). Highlights: new installer and configuration app, **ARM64** and **Windows 11** support, LED/dead-zone/rumble customization, Xbox One emulation, and more. Follow progress on [Discord](https://discord.nefarius.at/) or [Mastodon](https://fosstodon.org/@Nefarius). +Version 3 is the current stable release. Get the latest build from [releases](https://github.com/nefarius/DsHidMini/releases). Highlights: new installer and configuration app, **ARM64** and **Windows 11** support, LED/dead-zone/rumble customization, Xbox One emulation, and more. Support and updates on [Discord](https://discord.nefarius.at/) or [Mastodon](https://fosstodon.org/@Nefarius). ## Repository activity diff --git a/setup/Dialogs/BetaArticleDialog.xaml b/setup/Dialogs/OnlineDocumentationDialog.xaml similarity index 92% rename from setup/Dialogs/BetaArticleDialog.xaml rename to setup/Dialogs/OnlineDocumentationDialog.xaml index f3ab765cf..4ec6dfcea 100644 --- a/setup/Dialogs/BetaArticleDialog.xaml +++ b/setup/Dialogs/OnlineDocumentationDialog.xaml @@ -1,5 +1,5 @@ - A web article should have opened in your default Browser by now + A web page should have opened in your default browser by now. @@ -57,8 +57,8 @@ - - Open Beta Article + + Open documentation @@ -100,4 +100,4 @@ - \ No newline at end of file + diff --git a/setup/Dialogs/BetaArticleDialog.xaml.cs b/setup/Dialogs/OnlineDocumentationDialog.xaml.cs similarity index 50% rename from setup/Dialogs/BetaArticleDialog.xaml.cs rename to setup/Dialogs/OnlineDocumentationDialog.xaml.cs index 6485b62af..0f09068c4 100644 --- a/setup/Dialogs/BetaArticleDialog.xaml.cs +++ b/setup/Dialogs/OnlineDocumentationDialog.xaml.cs @@ -1,46 +1,27 @@ using System; using System.Diagnostics; -using System.IO; -using System.Text; using System.Windows; -using System.Windows.Controls; using System.Windows.Media.Imaging; using System.Windows.Navigation; -using WixSharp; using WixSharp.UI.Forms; using WixSharp.UI.WPF; -using IO = System.IO; - namespace Nefarius.DsHidMini.Setup.Dialogs; -/// -/// The standard LicenceDialog. -/// -/// -/// -/// -public partial class BetaArticleDialog : WpfDialog, IWpfDialog +public partial class OnlineDocumentationDialog : WpfDialog, IWpfDialog { - /// - /// Initializes a new instance of the class. - /// - public BetaArticleDialog() + public OnlineDocumentationDialog() { InitializeComponent(); } - /// - /// This method is invoked by WixSHarp runtime when the custom dialog content is internally fully initialized. - /// This is a convenient place to do further initialization activities (e.g. localization). - /// public void Init() { - DataContext = _model = new BetaArticleDialogModel { Host = ManagedFormHost }; + DataContext = _model = new OnlineDocumentationDialogModel { Host = ManagedFormHost }; } - private BetaArticleDialogModel _model; + private OnlineDocumentationDialogModel _model; private void GoNext_Click(object sender, RoutedEventArgs e) { @@ -51,24 +32,21 @@ private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs { try { - Process.Start(InstallScript.BetaArticleUrl.ToString()); + Process.Start(InstallScript.OnlineDocumentationUrl.ToString()); } catch { - // welp + // Not failing setup because a browser couldn't be launched } } } -/// -/// ViewModel for standard LicenceDialog. -/// -internal class BetaArticleDialogModel : NotifyPropertyChangedBase +internal class OnlineDocumentationDialogModel : NotifyPropertyChangedBase { private ManagedForm _host; private ISession Session => Host?.Runtime.Session; private IManagedUIShell Shell => Host?.Shell; - + public ManagedForm Host { get => _host; @@ -84,12 +62,10 @@ public ManagedForm Host public BitmapImage Banner => Session?.GetResourceBitmap("WixSharpUI_Bmp_Banner").ToImageSource() ?? Session?.GetResourceBitmap("WixUI_Bmp_Banner").ToImageSource(); - - public bool CanGoNext - => true; + public bool CanGoNext => true; public void GoNext() { Shell?.GoNext(); } -} \ No newline at end of file +} diff --git a/setup/InstallScript.cs b/setup/InstallScript.cs index d8e1819a1..7a2f3bba1 100644 --- a/setup/InstallScript.cs +++ b/setup/InstallScript.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Buffers; using System.Collections.Generic; @@ -36,7 +36,7 @@ internal class InstallScript { public const string ProductName = "Nefarius DsHidMini Driver"; - public static Uri BetaArticleUrl = new("https://docs.nefarius.at/projects/DsHidMini/Experimental/Version-3-Beta/"); + public static Uri OnlineDocumentationUrl = new("https://docs.nefarius.at/projects/DsHidMini/v3/How-to-Install/"); private static void Main() { @@ -110,8 +110,8 @@ private static void Main() When.After, Step.InstallFinalize, Condition.NOT_Installed), - // open beta article - new ManagedAction(CustomActions.OpenBetaArticle, Return.check, + // open online documentation + new ManagedAction(CustomActions.OpenOnlineDocumentation, Return.check, When.After, Step.InstallFinalize, Condition.NOT_Installed), @@ -152,7 +152,7 @@ private static void Main() .Add() .Add() .Add() - .Add() + .Add() .Add(); project.ManagedUI.ModifyDialogs.Add() @@ -339,19 +339,19 @@ public static ActionResult InstallBthPS3(Session session) } /// - /// Open beta article in default browser. + /// Open online documentation in default browser. /// [CustomAction] - public static ActionResult OpenBetaArticle(Session session) + public static ActionResult OpenOnlineDocumentation(Session session) { try { - Process.Start(InstallScript.BetaArticleUrl.ToString()); + Process.Start(InstallScript.OnlineDocumentationUrl.ToString()); } catch (Exception ex) { session.Log( - $"Beta article launch failed, exception: {ex}"); + $"Online documentation launch failed, exception: {ex}"); } return ActionResult.Success; @@ -375,7 +375,7 @@ public static ActionResult OpenDonationPage(Session session) catch (Exception ex) { session.Log( - $"Beta article launch failed, exception: {ex}"); + $"Donation page launch failed, exception: {ex}"); } return ActionResult.Success; From 7b4cbf2ea5e0888bd8acf5bac25214fc760e5e5e Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:17:01 +0000 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=93=9D=20Add=20docstrings=20to=20`v3-?= =?UTF-8?q?stable-release`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docstrings generation was requested by @nefarius. The following files were modified: * `setup/Dialogs/OnlineDocumentationDialog.xaml.cs` * `setup/InstallScript.cs` These file types are not supported: * `ControlApp/Views/Pages/DevicesPage.xaml` * `README.md` * `setup/Dialogs/OnlineDocumentationDialog.xaml` --- .../Dialogs/OnlineDocumentationDialog.xaml.cs | 26 +++++++++++++++++++ setup/InstallScript.cs | 18 +++++++++++++ 2 files changed, 44 insertions(+) diff --git a/setup/Dialogs/OnlineDocumentationDialog.xaml.cs b/setup/Dialogs/OnlineDocumentationDialog.xaml.cs index 0f09068c4..e68d7e761 100644 --- a/setup/Dialogs/OnlineDocumentationDialog.xaml.cs +++ b/setup/Dialogs/OnlineDocumentationDialog.xaml.cs @@ -11,11 +11,20 @@ namespace Nefarius.DsHidMini.Setup.Dialogs; public partial class OnlineDocumentationDialog : WpfDialog, IWpfDialog { + /// + /// Initializes a new instance of OnlineDocumentationDialog and initializes its WPF UI components. + /// public OnlineDocumentationDialog() { InitializeComponent(); } + /// + /// Initializes the dialog's view model and sets it as the dialog's DataContext. + /// + /// + /// Creates a new , assigns to its Host property, stores it in the backing field, and sets DataContext to the created model. + /// public void Init() { DataContext = _model = new OnlineDocumentationDialogModel { Host = ManagedFormHost }; @@ -23,11 +32,22 @@ public void Init() private OnlineDocumentationDialogModel _model; + /// + /// Handles the Next button click and advances the installer to the next dialog. + /// + /// The control that raised the click event. + /// Event data for the routed event. private void GoNext_Click(object sender, RoutedEventArgs e) { _model.GoNext(); } + /// + /// Attempts to open the application's online documentation URL in the user's default web browser. + /// + /// + /// Any exception thrown while launching the browser is caught and ignored so setup does not fail if the browser cannot be started. + /// private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e) { try @@ -64,6 +84,12 @@ public ManagedForm Host public bool CanGoNext => true; + /// + /// Advances the installer to the next step in the dialog sequence. + /// + /// + /// If a hosting shell is available, requests it to navigate to the next page; otherwise does nothing. + /// public void GoNext() { Shell?.GoNext(); diff --git a/setup/InstallScript.cs b/setup/InstallScript.cs index 7a2f3bba1..5d57d514f 100644 --- a/setup/InstallScript.cs +++ b/setup/InstallScript.cs @@ -38,6 +38,12 @@ internal class InstallScript public static Uri OnlineDocumentationUrl = new("https://docs.nefarius.at/projects/DsHidMini/v3/How-to-Install/"); + /// + /// Builds and emits the MSI installer for the Nefarius DsHidMini drivers and packaged artifacts. + /// + /// + /// Reads setup, driver, and filter versions from build variables and artifact file metadata; defines installer features and package contents; configures managed actions, custom actions, registry writes, UI dialogs, embedded reference assemblies, and control panel metadata; hooks post-install handling; and finally generates the MSI file. + /// private static void Main() { // grab main app version @@ -294,7 +300,11 @@ public static ActionResult InstallDrivers(Session session) /// /// Download and install BthPS3. + /// + /// Downloads metadata for the latest BthPS3 update and opens its download URL when the BthPS3 feature is enabled. /// + /// The MSI session used to check whether the BthPS3 feature is enabled and to record logs. + /// `ActionResult.Success` on completion. [CustomAction] [SuppressMessage("ReSharper", "InconsistentNaming")] public static ActionResult InstallBthPS3(Session session) @@ -340,7 +350,11 @@ public static ActionResult InstallBthPS3(Session session) /// /// Open online documentation in default browser. + /// + /// Opens the product's online documentation URL in the user's default browser. /// + /// The current MSI session used for logging. + /// `ActionResult.Success` to indicate the custom action completed; if launching the URL fails the exception is logged and the action still returns `ActionResult.Success`. [CustomAction] public static ActionResult OpenOnlineDocumentation(Session session) { @@ -359,7 +373,11 @@ public static ActionResult OpenOnlineDocumentation(Session session) /// /// Open donations page in default browser. + /// + /// Opens the donation web page in the user's default browser when the DonationFeature is enabled. /// + /// MSI session used to check feature state and to record failures to the installer log. + /// on completion. [CustomAction] public static ActionResult OpenDonationPage(Session session) { From cdf4ab942e8ad283acb60e4c454b5554a95990c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Mon, 30 Mar 2026 13:24:59 +0200 Subject: [PATCH 3/6] Update OnlineDocumentationDialog.xaml.cs --- setup/Dialogs/OnlineDocumentationDialog.xaml.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup/Dialogs/OnlineDocumentationDialog.xaml.cs b/setup/Dialogs/OnlineDocumentationDialog.xaml.cs index 0f09068c4..16ba4af7a 100644 --- a/setup/Dialogs/OnlineDocumentationDialog.xaml.cs +++ b/setup/Dialogs/OnlineDocumentationDialog.xaml.cs @@ -4,6 +4,7 @@ using System.Windows.Media.Imaging; using System.Windows.Navigation; +using WixSharp; using WixSharp.UI.Forms; using WixSharp.UI.WPF; @@ -11,6 +12,8 @@ namespace Nefarius.DsHidMini.Setup.Dialogs; public partial class OnlineDocumentationDialog : WpfDialog, IWpfDialog { + private OnlineDocumentationDialogModel _model; + public OnlineDocumentationDialog() { InitializeComponent(); @@ -21,8 +24,6 @@ public void Init() DataContext = _model = new OnlineDocumentationDialogModel { Host = ManagedFormHost }; } - private OnlineDocumentationDialogModel _model; - private void GoNext_Click(object sender, RoutedEventArgs e) { _model.GoNext(); From dcfade075ecc9e822aee68e091cdea74ade74862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 7 Jun 2026 11:51:41 +0200 Subject: [PATCH 4/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f9a9957bd..b49928b18 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ This solution contains **BSD-3-Clause** and other licensed components; see the i ## Installation -Pre-built binaries and instructions: [releases](https://github.com/nefarius/DsHidMini/releases). Installation steps: [How to Install](https://docs.nefarius.at/projects/DsHidMini/v2/How-to-Install/). +Pre-built binaries and instructions: [releases](https://github.com/nefarius/DsHidMini/releases). Installation steps: [How to Install](https://docs.nefarius.at/projects/DsHidMini/v3/How-to-Install/). ## Support From 53b5be274e8806cdf5e8781664a1b9822a9be3f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 7 Jun 2026 17:24:08 +0200 Subject: [PATCH 5/6] Added ControlApp packaging and .NET probe to setup --- setup/InstallScript.cs | 66 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/setup/InstallScript.cs b/setup/InstallScript.cs index 5d57d514f..54e8e14ed 100644 --- a/setup/InstallScript.cs +++ b/setup/InstallScript.cs @@ -95,8 +95,16 @@ private static void Main() new Files(driversFeature, @"..\artifacts\drivers\*.*"), new Files(driversFeature, @"..\artifacts\igfilter\*.*") ), - new File(driversFeature, "nefarius_DsHidMini_Updater.exe") + new File(driversFeature, "nefarius_DsHidMini_Updater.exe"), + new File(driversFeature, @"..\artifacts\bin\ControlApp.exe", + new FileShortcut("DsHidMini Control App", + @"%ProgramMenu%\Nefarius Software Solutions\DsHidMini")) ), + // check for .NET 9 Desktop Runtime before any files are laid down + new ManagedAction(CustomActions.CheckDotNetRuntime, Return.check, + When.Before, + Step.LaunchConditions, + Condition.NOT_Installed), // install drivers new ElevatedManagedAction(CustomActions.InstallDrivers, Return.check, When.After, @@ -106,6 +114,11 @@ private static void Main() new Error("9000", "Driver installation succeeded but a reboot is required to be fully operational. " + "After the setup is finished, please reboot the system before using the software."), + // .NET 9 Desktop Runtime missing + new Error("9001", + "The .NET 9 Desktop Runtime (x64) is required by DsHidMini Control App. " + + "Please download and install it from https://dotnet.microsoft.com/download/dotnet/9.0 " + + "and then re-run this installer."), // install BthPS3 new ManagedAction(CustomActions.InstallBthPS3, Return.check, When.After, @@ -211,6 +224,57 @@ private static void ProjectOnAfterInstall(SetupEventArgs e) public static class CustomActions { + /// + /// Verifies that the .NET 9 Desktop Runtime (x64) is installed before setup proceeds. + /// Aborts the install with a user-facing message when the runtime is absent. + /// + /// + /// Detection uses the filesystem rather than the registry: modern .NET installers + /// do not reliably populate HKLM\SOFTWARE\dotnet\Setup\InstalledVersions, but they + /// always create a versioned subdirectory under + /// %ProgramFiles%\dotnet\shared\Microsoft.WindowsDesktop.App. + /// + [CustomAction] + public static ActionResult CheckDotNetRuntime(Session session) + { + string runtimeDir = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), + "dotnet", "shared", "Microsoft.WindowsDesktop.App"); + + session.Log($"Probing .NET Desktop Runtime directory: {runtimeDir}"); + + try + { + if (Directory.Exists(runtimeDir)) + { + foreach (string versionDir in Directory.GetDirectories(runtimeDir)) + { + string dirName = Path.GetFileName(versionDir); + if (Version.TryParse(dirName, out Version? installedVersion) && + installedVersion.Major >= 9) + { + session.Log($".NET Desktop Runtime {installedVersion} found - prerequisite satisfied."); + return ActionResult.Success; + } + } + } + } + catch (Exception ex) + { + session.Log($"Failed to probe .NET 9 Desktop Runtime directory: {ex}"); + } + + session.Log(".NET 9 Desktop Runtime not found, aborting installation."); + + Record record = new(1); + record[1] = "9001"; + session.Message( + InstallMessage.User | (InstallMessage)MessageButtons.OK | (InstallMessage)MessageIcon.Error, + record); + + return ActionResult.Failure; + } + /// /// Put install logic here. /// From e2ba33995e604882c47a92523cb1618ea6569cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20H=C3=B6glinger-Stelzer?= Date: Sun, 7 Jun 2026 17:28:23 +0200 Subject: [PATCH 6/6] Update InstallScript.cs --- setup/InstallScript.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup/InstallScript.cs b/setup/InstallScript.cs index 54e8e14ed..090a1f9d9 100644 --- a/setup/InstallScript.cs +++ b/setup/InstallScript.cs @@ -250,7 +250,10 @@ public static ActionResult CheckDotNetRuntime(Session session) foreach (string versionDir in Directory.GetDirectories(runtimeDir)) { string dirName = Path.GetFileName(versionDir); - if (Version.TryParse(dirName, out Version? installedVersion) && + // strip pre-release suffix (e.g. "9.0.0-preview.3") before parsing + int dashIndex = dirName.IndexOf('-'); + string numericPart = dashIndex >= 0 ? dirName.Substring(0, dashIndex) : dirName; + if (Version.TryParse(numericPart, out Version? installedVersion) && installedVersion.Major >= 9) { session.Log($".NET Desktop Runtime {installedVersion} found - prerequisite satisfied.");