Fix Windows auto updater file locking issue

Implement deferred update mechanism using a helper batch script that applies
updates after the application exits, avoiding Windows file locking issues.

On Windows, the updater now:
- Stages update files and creates a helper batch script
- Launches the script as a detached process
- Exits the application
- The script waits for app closure, applies updates, and restarts Citron

Linux AppImage updates continue to work as before with the existing method.

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron
2025-11-01 19:19:02 +10:00
parent a462e66927
commit 0ce89925a2
4 changed files with 141 additions and 1 deletions

View File

@@ -334,6 +334,31 @@ void UpdaterDialog::ShowInstallingState() {
void UpdaterDialog::ShowCompletedState() {
current_state = State::Completed;
#ifdef _WIN32
// On Windows, launch the update helper script and exit immediately
ui->titleLabel->setText(QStringLiteral("Update ready!"));
ui->statusLabel->setText(QStringLiteral("Citron will now restart to apply the update..."));
ui->progressGroup->setVisible(false);
ui->downloadButton->setVisible(false);
ui->cancelButton->setVisible(false);
ui->closeButton->setVisible(false);
ui->restartButton->setVisible(false);
ui->progressBar->setValue(100);
ui->appImageSelectorLabel->setVisible(false);
ui->appImageSelector->setVisible(false);
// Give the user a moment to see the message
QTimer::singleShot(1500, this, [this]() {
if (updater_service->LaunchUpdateHelper()) {
QApplication::quit();
} else {
ShowErrorState();
ui->statusLabel->setText(QStringLiteral("Failed to launch update helper. Please restart Citron manually to apply the update."));
}
});
#else
// On Linux, show the restart button as before
ui->titleLabel->setText(QStringLiteral("Update ready!"));
ui->statusLabel->setText(QStringLiteral("The update has been downloaded and prepared "
"successfully. The update will be applied when you "
@@ -346,6 +371,7 @@ void UpdaterDialog::ShowCompletedState() {
ui->progressBar->setValue(100);
ui->appImageSelectorLabel->setVisible(false);
ui->appImageSelector->setVisible(false);
#endif
}
void UpdaterDialog::ShowErrorState() {