Fix update hang: allow dialog close after download; harden updater wait.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Exest 2026-07-31 17:18:11 +03:00
parent 2230d4c73f
commit ee5e2db953
3 changed files with 26 additions and 16 deletions

View File

@ -151,28 +151,36 @@ namespace Электронная_Фармация.Classes
private static void WriteUpdaterScript(string path) private static void WriteUpdaterScript(string path)
{ {
// Waits for app exit, copies files, keeps local DB/Logs, restarts exe. // Waits for app exit (max ~30s, then force-kill), copies files, keeps DB/Logs, restarts.
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine("@echo off"); sb.AppendLine("@echo off");
sb.AppendLine("setlocal"); sb.AppendLine("setlocal EnableDelayedExpansion");
sb.AppendLine("set \"SRC=%~1\""); sb.AppendLine("set \"SRC=%~1\"");
sb.AppendLine("set \"DST=%~2\""); sb.AppendLine("set \"DST=%~2\"");
sb.AppendLine("set \"EXENAME=%~3\""); sb.AppendLine("set \"EXENAME=%~3\"");
sb.AppendLine("set \"PID=%~4\""); sb.AppendLine("set \"PID=%~4\"");
sb.AppendLine("set \"N=0\"");
sb.AppendLine("echo Waiting for PID %PID% ... > \"%TEMP%\\elfisa-updater.log\""); sb.AppendLine("echo Waiting for PID %PID% ... > \"%TEMP%\\elfisa-updater.log\"");
sb.AppendLine(":waitloop"); sb.AppendLine(":waitloop");
sb.AppendLine("tasklist /FI \"PID eq %PID%\" 2>nul | find \"%PID%\" >nul"); sb.AppendLine("tasklist /FI \"PID eq %PID%\" 2>nul | findstr /C:\" %PID% \" >nul");
sb.AppendLine("if not errorlevel 1 ("); sb.AppendLine("if errorlevel 1 goto donewait");
sb.AppendLine(" timeout /t 1 /nobreak >nul"); sb.AppendLine("set /a N+=1");
sb.AppendLine(" goto waitloop"); sb.AppendLine("echo still alive n=!N! >> \"%TEMP%\\elfisa-updater.log\"");
sb.AppendLine("if !N! GEQ 30 (");
sb.AppendLine(" echo force kill %PID% >> \"%TEMP%\\elfisa-updater.log\"");
sb.AppendLine(" taskkill /PID %PID% /F >nul 2>&1");
sb.AppendLine(" goto donewait");
sb.AppendLine(")"); sb.AppendLine(")");
sb.AppendLine("timeout /t 1 /nobreak >nul"); // ping instead of timeout — timeout often hangs in hidden windows
sb.AppendLine("ping 127.0.0.1 -n 2 >nul");
sb.AppendLine("goto waitloop");
sb.AppendLine(":donewait");
sb.AppendLine("ping 127.0.0.1 -n 2 >nul");
sb.AppendLine("echo Copying update... >> \"%TEMP%\\elfisa-updater.log\""); sb.AppendLine("echo Copying update... >> \"%TEMP%\\elfisa-updater.log\"");
// /E copy tree; exclude local DB and logs from being overwritten/removed.
sb.AppendLine("robocopy \"%SRC%\" \"%DST%\" /E /R:2 /W:1 /NFL /NDL /NJH /NJS /XF efClient.db *.db /XD Logs"); sb.AppendLine("robocopy \"%SRC%\" \"%DST%\" /E /R:2 /W:1 /NFL /NDL /NJH /NJS /XF efClient.db *.db /XD Logs");
sb.AppendLine("set \"RC=%ERRORLEVEL%\""); sb.AppendLine("set \"RC=!ERRORLEVEL!\"");
sb.AppendLine("echo robocopy=%RC% >> \"%TEMP%\\elfisa-updater.log\""); sb.AppendLine("echo robocopy=!RC! >> \"%TEMP%\\elfisa-updater.log\"");
// robocopy 0-7 = success-ish sb.AppendLine("echo Starting \"%DST%\\%EXENAME%\" >> \"%TEMP%\\elfisa-updater.log\"");
sb.AppendLine("start \"\" /D \"%DST%\" \"%DST%\\%EXENAME%\""); sb.AppendLine("start \"\" /D \"%DST%\" \"%DST%\\%EXENAME%\"");
sb.AppendLine("exit /b 0"); sb.AppendLine("exit /b 0");
File.WriteAllText(path, sb.ToString(), Encoding.Default); File.WriteAllText(path, sb.ToString(), Encoding.Default);

View File

@ -53,8 +53,9 @@ namespace Электронная_Фармация.HelpForms
{ {
await AutoUpdater.ApplyUpdateAsync(_result, progress); await AutoUpdater.ApplyUpdateAsync(_result, progress);
lblMessage.Text = "Обновление скачано. Перезапуск..."; lblMessage.Text = "Обновление скачано. Перезапуск...";
// Нельзя звать Application.Exit() из async continuation — падает // Снимаем блокировку закрытия, иначе диалог зависает навечно
// «коллекция была изменена». Закрываем диалог; Form1 завершит процесс. // на «Перезапуск...» и updater ждёт PID, который не завершается.
_updating = false;
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;
Close(); Close();
} }
@ -86,7 +87,8 @@ namespace Электронная_Фармация.HelpForms
private void HF_UpdateAvailable_FormClosing(object sender, FormClosingEventArgs e) private void HF_UpdateAvailable_FormClosing(object sender, FormClosingEventArgs e)
{ {
if (_updating) // Блокируем только ручное закрытие во время скачивания.
if (_updating && DialogResult != DialogResult.OK)
{ {
e.Cancel = true; e.Cancel = true;
return; return;

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Можно задать все значения или принять номера сборки и редакции по умолчанию // Можно задать все значения или принять номера сборки и редакции по умолчанию
// используя "*", как показано ниже: // используя "*", как показано ниже:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.15.0")] [assembly: AssemblyVersion("1.0.16.0")]
[assembly: AssemblyFileVersion("1.0.15.0")] [assembly: AssemblyFileVersion("1.0.16.0")]