Bump to v1.9.0: fix the robocopy trailing-backslash bug — auto-updater finally works

The install helper's robocopy line was:
  robocopy "{stagingRoot}" "{installDir}" ...
installDir is AppContext.BaseDirectory, which always ends in a directory
separator, so the destination argument was a quoted path ending in a
backslash: "D:\...\publish\". Windows command-line parsing reads the \"
as an escaped quote, so robocopy never received a valid destination,
rejected the command line, and exited 16 (usage error, nothing copied)
instantly. The auto-updater has never worked in any release because of
this — v1.0-v1.2 failed silently, v1.3+ detected the failure and wrote
update-failed.txt but never fixed the robocopy line.

Fix: BuildInstallScript now strips trailing separators —
stagingArg = stagingRoot.TrimEnd('\','/'), installArg likewise — and
the robocopy line uses the trimmed forms. Verified by running the
corrected robocopy against real staged files: exit 3 (success), files
copied.

The broken helper is baked into every shipped build including v1.8, and
the helper is generated by the running version — so v1.8 and earlier
cannot auto-install v1.9. v1.9 must be installed by hand once; from v1.9
onward the updater works.

No wire-format or audio-pipeline changes — v1.5 through v1.9 interoperate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-05-19 13:49:44 +01:00
co-authored by Claude Opus 4.7
parent e6d47e229d
commit 4344e3439d
4 changed files with 48 additions and 20 deletions
+22
View File
@@ -20,6 +20,28 @@ internal sealed class AboutDialog : Form
/// updates" path.</summary>
private const string ReleaseNotes =
"""
RemSound v1.9
Critical auto-updater fix. No wire-format or
audio-pipeline changes v1.5 through v1.9 peers
interoperate.
Bug fix:
* The auto-updater now actually installs updates.
Every previous version had a fault in the update
step: the folder path handed to the file-copy
command ended in a backslash, which Windows
mis-read, so the copy was rejected and no files
were ever replaced. Check for updates would
download the new version but never apply it. That
copy step is fixed.
Because the fault was in the OLD version doing the
updating, v1.8 and earlier cannot install v1.9 for you
install v1.9 by hand once (download the zip, extract
it over your RemSound folder). From v1.9 onward, Check
for updates installs every update automatically.
RemSound v1.8
Updater polish and a rewritten user manual. No
+1 -1
View File
@@ -14,7 +14,7 @@
tag_name on the latest GitHub release; bump it on every public release. The
AssemblyVersion / FileVersion default to this value, and Assembly.GetName().Version
is what the About dialog and the updater both read. -->
<Version>1.8.0</Version>
<Version>1.9.0</Version>
</PropertyGroup>
<ItemGroup>
+10 -1
View File
@@ -232,6 +232,15 @@ internal sealed class RemSoundUpdater : IDisposable
var failureMarker = Path.Combine(installDir, "update-failed.txt");
var stagingDir = Path.Combine(installDir, "_update");
var remsoundExe = Path.Combine(installDir, "RemSound.exe");
// Robocopy source/destination, with any trailing directory separator stripped.
// CRITICAL BUG FIX (2026-05-19): installDir is AppContext.BaseDirectory, which ends
// in a backslash. A quoted path that ends in a backslash — "D:\dir\" — is mis-parsed
// on the command line: the \" is read as an ESCAPED quote, so robocopy never receives
// a valid destination argument and exits immediately with code 16 (no files copied).
// That silently broke EVERY auto-update in every release to date. The robocopy line
// below MUST use these trimmed forms, never the raw {installDir} / {stagingRoot}.
var stagingArg = stagingRoot.TrimEnd('\\', '/');
var installArg = installDir.TrimEnd('\\', '/');
return $"""
@echo off
setlocal
@@ -256,7 +265,7 @@ internal sealed class RemSoundUpdater : IDisposable
rem startup settings) and their data folders (logs / profiles / recordings). An update
rem replaces APP files only. build-release.ps1 already keeps those out of the release
rem zip; this is the second line of defence so a bad zip still can't clobber them.
robocopy "{stagingRoot}" "{installDir}" /E /IS /IT /NFL /NDL /NJH /NJS /R:60 /W:1 /XF _apply-update.cmd /XF _update-helper.log /XF update-failed.txt /XF remsound.config.json /XD logs profiles recordings _update /LOG+:"%LOG%"
robocopy "{stagingArg}" "{installArg}" /E /IS /IT /NFL /NDL /NJH /NJS /R:60 /W:1 /XF _apply-update.cmd /XF _update-helper.log /XF update-failed.txt /XF remsound.config.json /XD logs profiles recordings _update /LOG+:"%LOG%"
set "ROBO_EXIT=%ERRORLEVEL%"
echo %DATE% %TIME% robocopy exit=%ROBO_EXIT% >> "%LOG%"