-
Notifications
You must be signed in to change notification settings - Fork 25
Description
Implement Update Mechanism
Description
Implement an automatic update mechanism that checks for new versions on GitHub Releases when the application starts. When a new version is available, display a popup dialog allowing users to download and install the update. The mechanism should automatically detect whether the application is running as a SingleFile deployment or as an installed application (MSI), and provide the appropriate update method.
Requirements
Core Functionality
- Asynchronous Update Check: Check for updates in the background when the application starts (non-blocking)
- GitHub Releases Integration: Query GitHub Releases API to check for new versions
- Version Comparison: Compare current application version with latest release version
- Deployment Type Detection: Automatically detect if running as SingleFile or installed (MSI) version
- Update Dialog: Display a popup window when a new version is available
- SingleFile Update: Download and replace the single executable file for portable deployments
- MSI Update: Download and install MSI package for installed applications
User Experience
- Update check should not block application startup
- User must manually confirm download and installation (not fully automatic)
- Provide options to skip or postpone the update
- Show download progress
- Display current and new version information
- Automatically detect deployment type and show appropriate update method
Implementation Details
1. UpdateService
File: app/Sentinel.NLogViewer.App/Services/UpdateService.cs
- Check GitHub Releases API:
https://api.github.com/repos/boexler/NLogViewer/releases/latest - Compare versions using semantic versioning
- Deployment Type Detection:
- SingleFile: Check if
Assembly.GetEntryAssembly()?.Locationis empty or if running from non-ProgramFiles location - Installed: Check if application is in Program Files or has MSI installation registry entry
- SingleFile: Check if
- SingleFile Update:
- Download single executable from release assets (e.g.,
NLogViewer-SelfContained-win-x64-{version}.zip) - Extract executable to temporary location
- Replace current executable on next restart (or prompt user to restart)
- Download single executable from release assets (e.g.,
- MSI Update:
- Download MSI file from release assets
- Launch MSI installer process
- Use
System.Net.Http.HttpClientfor API calls and downloads
2. UpdateWindow
Files:
app/Sentinel.NLogViewer.App/UpdateWindow.xamlapp/Sentinel.NLogViewer.App/UpdateWindow.xaml.cs
Features:
- Display current version and new version
- Display deployment type (SingleFile or Installed)
- Download button
- Install/Update button (enabled after download completes)
- For SingleFile: "Update" button (replaces executable)
- For MSI: "Install" button (launches MSI installer)
- "Skip" / "Later" options
- Progress bar for download status
3. UpdateViewModel
File: app/Sentinel.NLogViewer.App/ViewModels/UpdateViewModel.cs
- Bind UpdateWindow to UpdateService
- Commands for Download/Install/Skip actions
- Progress tracking for download
4. Integration
File: app/Sentinel.NLogViewer.App/App.xaml.cs
- Register UpdateService as singleton in DI container
- Call async update check in
OnStartupmethod (non-blocking) - Show UpdateWindow when new version is detected
5. Deployment Type Detection
File: app/Sentinel.NLogViewer.App/Services/UpdateService.cs
Methods to detect deployment type:
SingleFile Detection:
- Check if
Assembly.GetEntryAssembly()?.Locationis empty or null - Check if
AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES")is null - Check if executable path is NOT in
Program FilesorProgram Files (x86) - Check if executable is in a user-writable location
Installed (MSI) Detection:
- Check if executable path is in
Program FilesorProgram Files (x86) - Check Windows Registry for MSI installation entry:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall- Look for product name matching application
- Check if
Assembly.GetEntryAssembly()?.Locationpoints to Program Files
Implementation:
public enum DeploymentType
{
SingleFile,
Installed
}
public DeploymentType DetectDeploymentType()
{
var entryAssembly = Assembly.GetEntryAssembly();
var location = entryAssembly?.Location;
var exePath = Environment.GetCommandLineArgs()[0];
// SingleFile: Location is typically empty
if (string.IsNullOrEmpty(location))
return DeploymentType.SingleFile;
// Check if running from Program Files (likely installed)
if (exePath.Contains("Program Files", StringComparison.OrdinalIgnoreCase))
return DeploymentType.Installed;
// Default to SingleFile for portable deployments
return DeploymentType.SingleFile;
}6. Version Management
- Current version: Read from
AssemblyInformationalVersionAttribute(already implemented inMainWindow.xaml.cs) - Latest version: Extract from GitHub Release
tag_nameorname - Implement semantic version comparison
7. Update Package Handling
SingleFile Deployment:
- Download ZIP file containing the single executable (e.g.,
NLogViewer-SelfContained-win-x64-{version}.zip) - Extract executable to
%TEMP%\NLogViewer\directory - Replace current executable:
- Option 1: Copy new executable to same directory with
.newextension, then on restart replace - Option 2: Use updater process that replaces executable after application closes
- Option 1: Copy new executable to same directory with
- Filter release assets by
.zipextension for SelfContained packages
MSI Installation:
- Download MSI file from release assets
- Save to
%TEMP%\NLogViewer\directory - Launch MSI using
Process.Start()with appropriate arguments - Filter release assets by
.msiextension
Configuration
- Repository owner/name:
boexler/NLogViewer(can be configured inappsettings.jsonor as constant) - Make update check optional/configurable
Dependencies
System.Net.Http(included in .NET)- Consider
SemanticVersioningNuGet package for robust version comparison
GitHub Workflow Integration
- Ensure GitHub Releases workflow uploads both:
- MSI packages as assets (e.g.,
NLogViewer-1.2.3.msi) - SingleFile ZIP packages as assets (e.g.,
NLogViewer-SelfContained-win-x64-1.2.3.zip)
- MSI packages as assets (e.g.,
- Package filenames should include version for easy identification
Acceptance Criteria
- UpdateService checks GitHub Releases on application startup
- Update check runs asynchronously without blocking UI
- Deployment type is correctly detected (SingleFile vs Installed)
- UpdateWindow displays when new version is available
- For SingleFile: User can download and update the executable
- For MSI: User can download and install MSI package
- Appropriate update method is shown based on deployment type
- User can skip or postpone update
- Download progress is displayed
- Version comparison works correctly with semantic versioning
- Error handling for network issues, missing releases, etc.
- SingleFile update handles executable replacement correctly (restart mechanism)
Related
- Current version display:
MainWindow.xaml.cs(line 36-46) - GitHub Releases workflow:
.github/workflows/release.yml - Version management: GitVersion (configured in
GitVersion.yml)