Release v1.0.25: fix auto-updater elevation

Апдейтер: повышение прав через cmd.exe /c вместо запуска .cmd напрямую
(ShellExecute runas на .cmd срабатывал не на всех системах — elevated
процесс молча не стартовал, обновление в Program Files не применялось,
клиент зацикливался на уведомлении). Payload переносится в ASCII-путь,
чтобы имя папки из архива не ломало аргумент SRC для robocopy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Exest 2026-08-07 10:38:08 +03:00
parent b10eba0984
commit 557f8667ad
2 changed files with 35 additions and 7 deletions

View File

@ -74,6 +74,24 @@ namespace Электронная_Фармация.Classes
throw new InvalidOperationException("В архиве не найден exe приложения."); throw new InvalidOperationException("В архиве не найден exe приложения.");
} }
// Переносим payload в путь без спецсимволов: имя корневой папки в архиве
// бывает в чужой кодировке, и такой путь ломает аргумент SRC у robocopy
// (особенно при запуске под elevated cmd с OEM-кодовой страницей).
var asciiPayload = Path.Combine(workRoot, "payload");
try
{
if (Directory.Exists(asciiPayload))
{
Directory.Delete(asciiPayload, true);
}
Directory.Move(payloadDir, asciiPayload);
payloadDir = asciiPayload;
}
catch
{
// Если перенос не удался — работаем с исходным путём.
}
var needsElevation = !IsDirectoryWritable(installDir); var needsElevation = !IsDirectoryWritable(installDir);
var updaterBat = Path.Combine(workRoot, "apply-update.cmd"); var updaterBat = Path.Combine(workRoot, "apply-update.cmd");
WriteUpdaterScript(updaterBat); WriteUpdaterScript(updaterBat);
@ -82,12 +100,12 @@ namespace Электронная_Фармация.Classes
? "Нужны права администратора для установки в Program Files..." ? "Нужны права администратора для установки в Program Files..."
: "Подготовка перезапуска..."); : "Подготовка перезапуска...");
var batchArgs = Quote(payloadDir) + " " + Quote(installDir) + " " +
Quote(Path.GetFileName(currentExe)) + " " +
Process.GetCurrentProcess().Id;
var psi = new ProcessStartInfo var psi = new ProcessStartInfo
{ {
FileName = updaterBat,
Arguments = Quote(payloadDir) + " " + Quote(installDir) + " " +
Quote(Path.GetFileName(currentExe)) + " " +
Process.GetCurrentProcess().Id,
UseShellExecute = true, UseShellExecute = true,
WorkingDirectory = workRoot, WorkingDirectory = workRoot,
WindowStyle = needsElevation ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden, WindowStyle = needsElevation ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden,
@ -95,9 +113,19 @@ namespace Электронная_Фармация.Classes
}; };
if (needsElevation) if (needsElevation)
{ {
// UAC prompt — без этого robocopy в Program Files молча не заменяет exe. // ВАЖНО: повышаем права через cmd.exe (PE-исполняемый), а НЕ через
// .cmd-файл напрямую. ShellExecute с verb=runas на .cmd срабатывает не
// на всех системах (у batch может не быть runas-ассоциации), из-за чего
// elevated-процесс молча не запускается и обновление не применяется.
psi.FileName = "cmd.exe";
psi.Arguments = "/c \"\"" + updaterBat + "\" " + batchArgs + "\"";
psi.Verb = "runas"; psi.Verb = "runas";
} }
else
{
psi.FileName = updaterBat;
psi.Arguments = batchArgs;
}
try try
{ {

View File

@ -32,6 +32,6 @@ using System.Runtime.InteropServices;
// пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ // пїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅ пїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
// пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ "*", пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ: // пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ "*", пїЅпїЅпїЅ пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ пїЅпїЅпїЅпїЅ:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.24.0")] [assembly: AssemblyVersion("1.0.25.0")]
[assembly: AssemblyFileVersion("1.0.24.0")] [assembly: AssemblyFileVersion("1.0.25.0")]