diff --git a/README.md b/README.md index 0d48bae..49b02f6 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,12 @@ Most AV kit ships set to DHCP, and on a bench or a fresh site there's usually no 2. Double-click it. Windows asks for administrator rights, because changing adapter settings and serving DHCP require them. 3. The exe isn't code-signed yet, so the first time Windows SmartScreen says "Windows protected your PC". Click **More info**, then **Run anyway**. +### Updates + +When the laptop has internet, ProDHCPServer checks GitHub for a newer release a few seconds after it starts. If there is one, a green banner offers **Install and restart**: it downloads the new exe, checks it against the SHA-256 published with the release, swaps it in place of the old one and restarts. The server has to be stopped first. Nothing is changed if any step fails, and the previous exe is deleted the next time the app starts. + +On an isolated AV network the check simply doesn't happen. Turn the start-up check off, or check by hand, under Settings > Updates. On a work laptop that only runs approved programs, Windows may block the new version from starting; the app then puts the old one back and says so. + ## Using it 1. Connect the device to your laptop's Ethernet port (directly or through a small switch) and power it on. @@ -104,9 +110,10 @@ Each phase ends with a hardware test pass on real AV equipment before the next o | What | Where | |---|---| -| Your settings (last adapter, profile in use, look and theme) | `%LOCALAPPDATA%\ProDHCPServer\settings.json` | +| Your settings (last adapter, profile in use, look and theme, update check) | `%LOCALAPPDATA%\ProDHCPServer\settings.json` | | Your profiles | `%LOCALAPPDATA%\ProDHCPServer\profiles.json` | | Adapter backup (only while a session runs, or after a crash) | `%ProgramData%\ProDHCPServer\adapter-backup.json` | +| The previous version, for a moment after an update | `ProDHCPServer.exe.old` next to the exe, deleted on the next start | While serving, the app also adds two Windows Firewall rules for this exe only: one so it can receive DHCP traffic (UDP 67 and 68), and one on wired adapters so it can hear devices announcing themselves (mDNS, UPnP, vendor discovery). Both are removed on Stop. diff --git a/docs/hardware-test-updates.md b/docs/hardware-test-updates.md new file mode 100644 index 0000000..2299de7 --- /dev/null +++ b/docs/hardware-test-updates.md @@ -0,0 +1,47 @@ +# Update checker test + +About 15 minutes on the unmanaged laptop, with internet. No AV devices needed. + +The updater can only update to a release that's already published on GitHub, so this test updates a test build to the newest published release (v1.1.0). v1.1.0 doesn't have the updater itself, so after the update it leaves `ProDHCPServer.exe.old` behind; delete it by hand at the end. + +Download `ProDHCPServer.exe` from this PR's latest **Build and test** run (Actions tab → run → Artifacts → `ProDHCPServer-win-x64`) and put it in a folder of its own, for example `C:\Tools\ProDHCPServer\`. Click **More info → Run anyway** on the SmartScreen warning. + +Tick each box. If something fails, use **Export log…** and send me the file. + +## 1. Test builds don't nag + +- [ ] Start the app with internet. After 10 seconds there is **no** green update banner (test builds only check when asked). +- [ ] Open Settings (gear, or Ctrl+,) and scroll to **Updates**. It says "This is test build 0.1.… It doesn't check for updates by itself; use Check now." + +## 2. Offline + +- [ ] Unplug or turn off the internet connection (Wi-Fi off, no network cable to the internet). +- [ ] Press **Check now**. Within about 10 seconds it says "Couldn't reach GitHub to check for updates. That's normal on an isolated AV network…". No error banner, no popup. +- [ ] The app otherwise works as normal: **Start** and **Stop** a session on a device or an empty port. + +## 3. Check and skip + +- [ ] Reconnect the internet. Press **Check now**. It says "Version 1.1.0 is available. You have test build 0.1.…", and the green banner appears at the top of the main window with **Install and restart**, **What's new**, **Not now** and **Skip this version**. +- [ ] **What's new** opens the release page in your normal browser. +- [ ] **Not now** hides the banner. + +## 4. Can't install while serving + +- [ ] Press **Check now** again so the banner is back, then **Start** the server. +- [ ] **Install and restart** is greyed out and the banner says "Stop the server first: installing restarts ProDHCPServer." +- [ ] Press **Stop**. **Install and restart** becomes clickable. + +## 5. Install + +- [ ] Press **Install and restart**. The banner shows "Downloading 1.1.0… nn%" with a progress bar, then the window closes and ProDHCPServer opens again by itself within a few seconds, with **no** UAC prompt. +- [ ] The log's first line says "ProDHCPServer 1.1.0 started (administrator)." +- [ ] In the folder, `ProDHCPServer.exe` is the new version (right-click → Properties → Details → Product version 1.1.0) and `ProDHCPServer.exe.old` is the test build. Close the app and delete the `.old` file. + +## Later, once a release with the updater is out + +When the release after this one is published, run the earlier release with the updater and check: + +- [ ] A few seconds after start, the green banner appears without pressing anything. +- [ ] **Skip this version**, then restart the app: no banner. **Check now** in Settings still offers it. +- [ ] Untick **Check for a new version when ProDHCPServer starts**, restart: no check in the log. +- [ ] After **Install and restart**, the log says "started (administrator) after updating." and `ProDHCPServer.exe.old` is gone within a few seconds. diff --git a/src/ProDHCPServer.App/App.xaml.cs b/src/ProDHCPServer.App/App.xaml.cs index 7a3dbce..0f2a78b 100644 --- a/src/ProDHCPServer.App/App.xaml.cs +++ b/src/ProDHCPServer.App/App.xaml.cs @@ -42,7 +42,10 @@ protected override void OnStartup(StartupEventArgs e) return; } - _singleInstance = new Mutex(true, @"Global\ProDHCPServer.SingleInstance", out bool first); + _singleInstance = new Mutex(true, SingleInstanceName, out bool first); + // Started by an update: the previous version is still closing, so give it time to let go. + bool updated = e.Args.Contains(UpdateViewModel.UpdatedFlag); + if (!first && updated) first = WaitForPreviousVersion(_singleInstance); if (!first) { MessageBox.Show("ProDHCPServer is already running. Two copies would fight over the adapter, so this one will close.", @@ -52,7 +55,9 @@ protected override void OnStartup(StartupEventArgs e) } _log = new SessionLog(); - _log.Add(LogSeverity.Info, LogCategory.App, $"ProDHCPServer {Version} started (administrator)."); + _log.Add(LogSeverity.Info, LogCategory.App, updated + ? $"ProDHCPServer {Version} started (administrator) after updating." + : $"ProDHCPServer {Version} started (administrator)."); var adapters = new WindowsAdapterControl(); var sessions = new AdapterSessionManager(adapters, new FileSessionStore(Path.Combine(DataFolder, "adapter-backup.json"))); _controller = new ServerController(adapters, sessions, _log, Version); @@ -78,6 +83,27 @@ protected override void OnStartup(StartupEventArgs e) window.Show(); } + private const string SingleInstanceName = @"Global\ProDHCPServer.SingleInstance"; + + /// + /// Lets go of the one-copy lock just before an update starts the new version, so it can start even if + /// it's an older build without . undoes it. + /// + public void ReleaseSingleInstance() + { + _singleInstance?.ReleaseMutex(); + _singleInstance?.Dispose(); + _singleInstance = null; + } + + public void RetakeSingleInstance() => _singleInstance ??= new Mutex(true, SingleInstanceName, out _); + + private static bool WaitForPreviousVersion(Mutex mutex) + { + try { return mutex.WaitOne(TimeSpan.FromSeconds(30)); } + catch (AbandonedMutexException) { return true; } // it exited without releasing: the mutex is ours now + } + private void OnUiException(object sender, DispatcherUnhandledExceptionEventArgs e) { // Keep running: show the error rather than vanish with the adapter half-configured. diff --git a/src/ProDHCPServer.App/MainWindow.xaml b/src/ProDHCPServer.App/MainWindow.xaml index 34fd4f9..2061a85 100644 --- a/src/ProDHCPServer.App/MainWindow.xaml +++ b/src/ProDHCPServer.App/MainWindow.xaml @@ -144,6 +144,35 @@ + + + + + + + + +