beeradmoore/dlss-swapper · error · Exception
Could not launch installer
Error message
Could not launch installer
What it means
After downloading the installer to a temp file, DownloadAndInstallAsync launches it with Process.Start using UseShellExecute = true. Process.Start returning null means Windows could not start the installer process, so the updater throws instead of exiting the app and leaving the user with a silent failure.
Solutions
- Check antivirus quarantine logs and whitelist the downloaded installer; re-run the update.
- Verify the temp download file exists and is a valid executable (check size/signature) before Process.Start.
- Ensure no other process has locked the temp file; reboot and retry the update.
- Manually download the installer from the GitHub releases page and run it yourself.
Example fix
// before
var installerProcess = Process.Start(processStartInfo);
if (installerProcess is null)
throw new Exception("Could not launch installer");
// after
if (File.Exists(tempDownloadFile) == false)
throw new Exception($"Installer not found at {tempDownloadFile}");
var installerProcess = Process.Start(processStartInfo);
if (installerProcess is null)
throw new Exception($"Could not launch installer at {tempDownloadFile}. It may be blocked by antivirus."); Defensive patterns
Strategy: validation
Validate before calling
// Verify the installer exists and is non-trivially sized before launching
if (File.Exists(tempDownloadFile) == false || new FileInfo(tempDownloadFile).Length < 1024)
{
// don't attempt Process.Start; treat as failed download
} Type guard
bool CanLaunchInstaller(string path) => File.Exists(path) && new FileInfo(path).Length > 0;
Try / catch
try
{
await updater.DownloadAndInstallAsync();
}
catch (Exception ex) when (ex.Message == "Could not launch installer")
{
logger.LogWarning(ex, "Installer launch blocked; suggest manual install");
// show dialog linking to the GitHub releases page
} Prevention
- Verify the downloaded installer exists and has a plausible size/signature before Process.Start
- Check antivirus/SmartScreen exclusion status for the temp download directory
- Download to a stable, app-owned temp path rather than one that may be cleaned mid-flow
- Provide a manual-install fallback path (open the releases page) when launch fails
When it happens
Trigger: Process.Start(processStartInfo) returns null: the temp installer file is missing or locked, the file association for .exe is broken, security software blocks execution of the downloaded file, or the temp path contains characters the shell cannot resolve.
Common situations: Antivirus (Defender or third-party) quarantining the downloaded installer, the temp file deleted between download and launch, corrupted download producing an invalid executable, or running in an environment (e.g. service context) where ShellExecute cannot resolve the handler.
Related errors
- DownloadFileToStreamAsync returned false.
- Could not detect ubisoftConnectInstallsKey.
- Process exit code was
- Failed to load DLL
AI-assisted analysis of beeradmoore/dlss-swapper@ab9b1e2d4b (2026-09-15).
Data as JSON: /api/errors/ea8624e881fe32b5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Data/GitHub/GitHubUpdater.cs:436
Title = ResourceHelper.GetString("GitHubUpdater_Updating_Title"),
Content = new ProgressRing() { IsIndeterminate = true },
};
_ = updatingDialog.ShowAsync();
// Give the popup time to show.
await Task.Delay(500);
try
{
var processStartInfo = new ProcessStartInfo()
{
FileName = tempDownloadFile,
UseShellExecute = true,
};
var installerProcess = Process.Start(processStartInfo);
if (installerProcess is null)
{
throw new Exception("Could not launch installer");
}
// Close DLSS Swapper so the installer can install
Application.Current.Exit();
}
catch (Exception err)
{
Logger.Error(err);
updatingDialog.Hide();
var errorDialog = new EasyContentDialog(xamlRoot)
{
Title = ResourceHelper.GetString("General_Error"),
Content = ResourceHelper.GetString("GitHubUpdater_CouldNotRunInstaller"),
PrimaryButtonText = ResourceHelper.GetString("GitHubUpdater_ViewUpdate"),
CloseButtonText = ResourceHelper.GetString("General_Cancel"),
DefaultButton = ContentDialogButton.Primary,View on GitHub (pinned to ab9b1e2d4b)