diff --git a/src/RemSound.App/MainForm.cs b/src/RemSound.App/MainForm.cs
index f37bb7b..5d75536 100644
--- a/src/RemSound.App/MainForm.cs
+++ b/src/RemSound.App/MainForm.cs
@@ -2205,6 +2205,12 @@ public sealed class MainForm : Form
{
var state = ServiceControl.Query();
status.Text = "Service: " + DescribeServiceState(state);
+ // Surface the running version + when it (re)started, so a self-update is visible at a glance.
+ if (state is ServiceState.Running or ServiceState.Stopped && ServiceStore.LoadStatus() is { Version: { } ver } st)
+ {
+ status.Text += $" — version {ver}";
+ if (state == ServiceState.Running && st.StartedUtc != default) status.Text += $", running since {DescribeAgo(st.StartedUtc)}";
+ }
var installed = state != ServiceState.NotInstalled;
install.Enabled = !installed;
uninstall.Enabled = installed;
@@ -2214,6 +2220,16 @@ public sealed class MainForm : Form
return serviceMenu;
}
+ private static string DescribeAgo(DateTime utc)
+ {
+ var span = DateTime.UtcNow - utc;
+ if (span < TimeSpan.Zero) span = TimeSpan.Zero;
+ if (span.TotalMinutes < 1) return "just now";
+ if (span.TotalHours < 1) return $"{(int)span.TotalMinutes} min ago";
+ if (span.TotalDays < 1) return $"{(int)span.TotalHours} h ago";
+ return $"{(int)span.TotalDays} d ago";
+ }
+
private static string DescribeServiceState(ServiceState s) => s switch
{
ServiceState.NotInstalled => "not installed",
diff --git a/src/RemSound.App/RemSoundService.cs b/src/RemSound.App/RemSoundService.cs
index a1e1f46..ac9381d 100644
--- a/src/RemSound.App/RemSoundService.cs
+++ b/src/RemSound.App/RemSoundService.cs
@@ -40,7 +40,12 @@ public sealed class RemSoundService : ServiceBase
protected override void OnStart(string[] args)
{
log = new RemSoundLog { Enabled = SafeServiceLogging() };
- log.Event("service: OnStart");
+ var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
+ var versionText = version is null ? "?" : $"{version.Major}.{version.Minor}";
+ log.Event($"service: OnStart, version {versionText}");
+ // Record the running version + start time so the app's Service menu can show them — this is how a
+ // self-update is visible (the version bumps and the start time is recent).
+ try { ServiceStore.SaveStatus(new ServiceStore.ServiceStatus { Version = versionText, StartedUtc = DateTime.UtcNow }); } catch { }
host = ServiceSendHost.FromConfig(msg => log?.Event(msg));
worker = new Thread(() =>
{
diff --git a/src/RemSound.App/SelfTest.cs b/src/RemSound.App/SelfTest.cs
index 5b5c7f7..adc7ee7 100644
--- a/src/RemSound.App/SelfTest.cs
+++ b/src/RemSound.App/SelfTest.cs
@@ -732,6 +732,10 @@ internal static class SelfTest
Check(back is not null && back.WasapiSendMode == "applications" && back.SelectedConnectedPeers.Contains("10.0.0.5"),
"the service profile must round-trip through the machine-wide store");
Check(ServiceStore.LoadLoggingEnabled(), "service logging flag must round-trip");
+
+ // Running status (version + start time) round-trips — this is what the Service menu shows.
+ ServiceStore.SaveStatus(new ServiceStore.ServiceStatus { Version = "5.3", StartedUtc = DateTime.UtcNow });
+ Check(ServiceStore.LoadStatus()?.Version == "5.3", "the service running-status version must round-trip");
}
finally { ServiceStore.TestDirectoryOverride = saved; }
diff --git a/src/RemSound.Core/ServiceStore.cs b/src/RemSound.Core/ServiceStore.cs
index 140a4f0..76ae3d4 100644
--- a/src/RemSound.Core/ServiceStore.cs
+++ b/src/RemSound.Core/ServiceStore.cs
@@ -66,5 +66,28 @@ public static class ServiceStore
/// True once a service profile has been configured.
public static bool IsConfigured() => File.Exists(ProfilePath);
+ // === Running status (written by the service on start, read by the app's Service menu) ===
+ private static string StatusPath => Path.Combine(Directory, "status.json");
+
+ /// The version + start time the service last recorded — so the interactive app can show
+ /// which version is running and when it (re)started, which is how you SEE a self-update land.
+ public sealed class ServiceStatus
+ {
+ public string? Version { get; set; }
+ public DateTime StartedUtc { get; set; }
+ }
+
+ public static void SaveStatus(ServiceStatus status)
+ {
+ try { System.IO.Directory.CreateDirectory(Directory); File.WriteAllText(StatusPath, JsonSerializer.Serialize(status)); }
+ catch { /* best-effort */ }
+ }
+
+ public static ServiceStatus? LoadStatus()
+ {
+ try { return File.Exists(StatusPath) ? JsonSerializer.Deserialize(File.ReadAllText(StatusPath)) : null; }
+ catch { return null; }
+ }
+
private sealed class ServiceSettings { public bool LoggingEnabled { get; set; } }
}