diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3fc32f1c..75364d5f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,21 @@ That paragraph is not decoration: the release workflow copies each entry verbati
the GitHub release body and the announcement discussion, so it is the first thing a
prospective user reads. CI fails a pull request whose newest entry is missing it.
+## [1.130.34] - 2026-10-21
+
+**The Delete key no longer takes a row off a list while nothing changes on the PC.**
+
+### Fixed
+
+- **Pressing Delete on Startup Manager, Uninstaller and six other lists removed the selected row and did nothing
+ else.** Windows' list control takes the selected row off its list on Delete unless it is told not to, and the
+ eight lists that can be ticked or switched never told it: Startup Manager, Uninstaller, Right-click Menu,
+ Environment Variables, Preinstalled Apps, App Updates, Browser Cleaner and Windows Update. The startup program
+ still started with Windows and the app stayed installed. On Environment Variables, Apply then deleted nothing,
+ and on Preinstalled Apps the hidden row stayed ticked, so Remove selected could remove an app no longer on
+ screen. Delete now does nothing in every list, and a row goes only through its own button and confirmation.
+ Since each list was added, the oldest in 0.3.0.
+
## [1.130.33] - 2026-10-21
**CSV exports open in Excel in your own region, with accented names intact.**
diff --git a/README.md b/README.md
index 7fb15f8e..f25300ca 100644
--- a/README.md
+++ b/README.md
@@ -238,6 +238,10 @@ or uninstalls is reachable from a bare keypress. On Drivers, Windows Update and
drivers, List updates and Analyze. Pressing it during a refresh that is already running does nothing
rather than starting a second one.
+**`Delete` in a list does nothing.** A startup program, an app, a variable or a menu entry is removed only
+through its own button and that button's confirmation, so a stray key press never takes a row off a list
+while it stays on the PC.
+
**Focus stays where you were when a list refreshes.** A refresh rebuilds a list's rows, and the button or cell
you were on used to go with them, leaving focus at the top of the window. Now focus comes back to the same
control in the same row: after F5 on Services, after putting a change back on Undo Changes, and on every table
diff --git a/SysManager/SysManager.IntegrationTests/StartupViewUiTests.cs b/SysManager/SysManager.IntegrationTests/StartupViewUiTests.cs
new file mode 100644
index 00000000..f0176ca0
--- /dev/null
+++ b/SysManager/SysManager.IntegrationTests/StartupViewUiTests.cs
@@ -0,0 +1,76 @@
+// SysManager · StartupViewUiTests
+// Author: laurentiu021 · https://github.com/laurentiu021/SystemManager
+// License: MIT
+
+using System.Collections.ObjectModel;
+using System.Windows;
+using System.Windows.Automation;
+using System.Windows.Controls;
+using System.Windows.Media;
+using SysManager.Models;
+using SysManager.Views;
+
+namespace SysManager.IntegrationTests;
+
+///
+/// The Delete key on Startup Manager's list leaves the list alone (#2809).
+///
+///
+/// WPF's DataGrid takes the selected row off its collection on Delete unless it is told not to, and the row
+/// vanished while the program still started with Windows. The guard reads the attribute on every editable grid; this
+/// presses the key on the real XAML, so the attribute is seen to do what the guard trusts it to.
+/// The view is given only the list it shows, not a StartupViewModel: the view model's scan hands its
+/// result to the application's dispatcher once a test has made one, and nothing pumps that dispatcher on
+/// 's thread, so waiting for the scan would wait forever. The grid is what is under test, and
+/// it binds the list by name.
+///
+[Collection("Network")]
+public sealed class StartupViewUiTests
+{
+ /// What the view binds the grid to, and nothing else.
+ private sealed class OnlyTheList
+ {
+ public ObservableCollection Entries { get; } =
+ [
+ new() { Name = "Contoso Updater", Command = @"C:\Program Files\Contoso\update.exe", Publisher = "Contoso",
+ Source = StartupSource.RegistryCurrentUser },
+ new() { Name = "Fabrikam Sync", Command = @"C:\Program Files\Fabrikam\sync.exe", Publisher = "Fabrikam",
+ Source = StartupSource.RegistryCurrentUser },
+ ];
+ }
+
+ [Fact]
+ public void TheDeleteKey_LeavesTheListAlone()
+ {
+ StaHelper.Run(() =>
+ {
+ AppResources.Ensure();
+ var shown = new OnlyTheList();
+ var view = new StartupView { DataContext = shown };
+ view.Measure(new Size(1400, 1000));
+ view.Arrange(new Rect(0, 0, 1400, 1000));
+ view.UpdateLayout();
+
+ var grid = Assert.Single(Descendants(view),
+ g => AutomationProperties.GetName(g) == "Startup programs");
+ Assert.Equal(2, grid.Items.Count);
+ grid.SelectedIndex = 0;
+
+ Assert.False(DataGrid.DeleteCommand.CanExecute(null, grid));
+ DataGrid.DeleteCommand.Execute(null, grid);
+
+ Assert.Equal(["Contoso Updater", "Fabrikam Sync"], shown.Entries.Select(e => e.Name));
+ });
+ }
+
+ private static IEnumerable Descendants(DependencyObject root) where T : DependencyObject
+ {
+ var count = VisualTreeHelper.GetChildrenCount(root);
+ for (var i = 0; i < count; i++)
+ {
+ var child = VisualTreeHelper.GetChild(root, i);
+ if (child is T match) yield return match;
+ foreach (var deeper in Descendants(child)) yield return deeper;
+ }
+ }
+}
diff --git a/SysManager/SysManager.Tests/ArchitectureTests.cs b/SysManager/SysManager.Tests/ArchitectureTests.cs
index 7bced2d3..e2ccaf84 100644
--- a/SysManager/SysManager.Tests/ArchitectureTests.cs
+++ b/SysManager/SysManager.Tests/ArchitectureTests.cs
@@ -854,6 +854,53 @@ public void EveryCsvExport_IsWrittenThroughCsv_InTheUsersRegion()
[GeneratedRegex(@"(?
+ /// Every grid a user can edit turns off the Delete key, which would otherwise take the selected row off the list.
+ ///
+ ///
+ /// WPF's DataGrid removes the selected rows from its collection on Delete whenever it is not read-only and
+ /// CanUserDeleteRows keeps its default of true. Eight grids that are editable for a tick or a switch never
+ /// turned it off, so the row vanished while nothing changed on the PC: the program still started with Windows,
+ /// Environment Variables' Apply deleted nothing, and Preinstalled Apps could remove an app no longer on screen
+ /// (#2809). A read-only grid needs nothing, because WPF refuses Delete on one.
+ ///
+ [Fact]
+ public void EveryEditableGrid_TurnsOffTheDeleteKey()
+ {
+ var views = Path.Combine(TestPaths.AppProject(), "Views");
+ var offenders = new List();
+ var grids = 0;
+ var editable = 0;
+
+ foreach (var file in Directory.EnumerateFiles(views, "*.xaml").Order(StringComparer.Ordinal))
+ {
+ var doc = XDocument.Parse(WithoutXamlComments(File.ReadAllText(file)));
+ foreach (var grid in doc.Descendants().Where(e => e.Name.LocalName == "DataGrid"))
+ {
+ grids++;
+ if ((string?)grid.Attribute("IsReadOnly") == "True") continue;
+ editable++;
+ if ((string?)grid.Attribute("CanUserDeleteRows") != "False")
+ {
+ var name = (string?)grid.Attributes()
+ .FirstOrDefault(a => a.Name.LocalName == "AutomationProperties.Name")?.Value ?? "a grid";
+ offenders.Add($"{Path.GetFileName(file)}: {name}");
+ }
+ }
+ }
+
+ // Vacuity floor: 35 grids when measured, 11 of them editable — App Blocker, App Updates, Browser Cleaner,
+ // Right-click Menu, Preinstalled Apps, DNS & Hosts, Environment Variables, Shortcut Cleaner, Startup Manager,
+ // Uninstaller and Windows Update.
+ Assert.True(grids >= 35 && editable >= 11,
+ $"{grids} grids and {editable} editable ones were found, out of 35 and 11 measured — the parse is out of "
+ + "date, so a pass proves nothing.");
+
+ Assert.True(offenders.Count == 0,
+ "an editable grid leaves the Delete key on, so pressing it takes the selected row off the list while "
+ + "nothing changes on the PC. Set CanUserDeleteRows=\"False\":\n " + string.Join("\n ", offenders));
+ }
+
///
/// Every StatusFooter names its own progress bar, and no view re-inlines the block it replaced.
///
diff --git a/SysManager/SysManager/SysManager.csproj b/SysManager/SysManager/SysManager.csproj
index eb874759..810149ac 100644
--- a/SysManager/SysManager/SysManager.csproj
+++ b/SysManager/SysManager/SysManager.csproj
@@ -13,9 +13,9 @@
$(NoWarn);NU1603;NU1701
false
- 1.130.33
- 1.130.33.0
- 1.130.33.0
+ 1.130.34
+ 1.130.34.0
+ 1.130.34.0
SysManager
SysManager — Windows system monitoring toolkit by laurentiu021. Network, updates, health, logs, safe deep cleanup.
https://github.com/laurentiu021/SystemManager
diff --git a/SysManager/SysManager/Views/AppUpdatesView.xaml b/SysManager/SysManager/Views/AppUpdatesView.xaml
index f0afe81c..02efe926 100644
--- a/SysManager/SysManager/Views/AppUpdatesView.xaml
+++ b/SysManager/SysManager/Views/AppUpdatesView.xaml
@@ -38,7 +38,7 @@