Merge install-detach-26 4d3aa6e4 into release-0.3.26 (the installer's detach step logs the OS error, copies through a .part name, runs the source in place when no copy can be made, and under a job refuses rather than installing in place; take 3b's class on PC 2; known-failed first)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
commit
0fd93532b3
2 changed files with 79 additions and 17 deletions
|
|
@ -169,31 +169,77 @@ begin
|
|||
Result := ExpandConstant('{localappdata}\igneum\app\updates\install-{#AppVersion}-detached.log');
|
||||
end;
|
||||
|
||||
// Copies this installer beside the app's data and starts the copy through a one-shot task. True when the task started.
|
||||
// The OS's words for the last error, for the log (PC 2, take 3b, 8 October 2026: "could not copy" with no reason).
|
||||
function LastErrorWords: String;
|
||||
var
|
||||
E: Integer;
|
||||
begin
|
||||
E := DLLGetLastError;
|
||||
Result := IntToStr(E) + ' ' + SysErrorMessage(E);
|
||||
end;
|
||||
|
||||
// The installer's copy beside the app's data, or the source itself when no copy can be made (the job folder persists
|
||||
// after the job; the detached task may run from it). Empty when neither can be used.
|
||||
function DetachSource: String;
|
||||
var
|
||||
Dir, Copy, Temp, Src: String;
|
||||
begin
|
||||
Result := '';
|
||||
Src := ExpandConstant('{srcexe}');
|
||||
if not FileExists(Src) then
|
||||
begin
|
||||
Log('detach: the source ' + Src + ' does not exist (' + LastErrorWords + ')');
|
||||
exit;
|
||||
end;
|
||||
Dir := ExpandConstant('{localappdata}\igneum\app\updates');
|
||||
if not DirExists(Dir) then
|
||||
begin
|
||||
if not ForceDirectories(Dir) then
|
||||
Log('detach: could not create ' + Dir + ' (' + LastErrorWords + ')');
|
||||
end;
|
||||
Copy := Dir + '\Igneum-Miner-Setup-{#AppVersion}.exe';
|
||||
Temp := Dir + '\Igneum-Miner-Setup-{#AppVersion}.exe.part';
|
||||
if DirExists(Dir) then
|
||||
begin
|
||||
DeleteFile(Temp);
|
||||
if FileCopy(Src, Temp, False) then
|
||||
begin
|
||||
DeleteFile(Copy);
|
||||
if RenameFile(Temp, Copy) then
|
||||
begin
|
||||
Result := Copy;
|
||||
exit;
|
||||
end;
|
||||
Log('detach: copied to ' + Temp + ' but could not rename it to ' + Copy + ' (' + LastErrorWords + '); the task runs the .part copy');
|
||||
Result := Temp;
|
||||
exit;
|
||||
end;
|
||||
Log('detach: could not copy ' + Src + ' to ' + Temp + ' (' + LastErrorWords + ')');
|
||||
end;
|
||||
// no copy: the source itself, from where it is (a job's folder persists after the job)
|
||||
Log('detach: the task runs the source in place: ' + Src);
|
||||
Result := Src;
|
||||
end;
|
||||
|
||||
// Starts the detached installer through a one-shot task. True when the task started.
|
||||
function RelaunchDetached: Boolean;
|
||||
var
|
||||
Dir, Copy, Args, Cmd: String;
|
||||
Copy, Args, Cmd: String;
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
Dir := ExpandConstant('{localappdata}\igneum\app\updates');
|
||||
ForceDirectories(Dir);
|
||||
Copy := Dir + '\Igneum-Miner-Setup-{#AppVersion}.exe';
|
||||
if not FileCopy(ExpandConstant('{srcexe}'), Copy, False) then
|
||||
begin
|
||||
Log('detach: could not copy ' + ExpandConstant('{srcexe}') + ' to ' + Copy);
|
||||
exit;
|
||||
end;
|
||||
Copy := DetachSource;
|
||||
if Copy = '' then exit;
|
||||
Args := '/VERYSILENT /NORESTART /SUPPRESSMSGBOXES /IGNOTA=' + ExpandConstant('{param:IGNOTA|0}') + ' /IGDETACHED=1 /LOG="' + DetachLogPath + '"';
|
||||
Cmd := '/Create /F /SC ONCE /ST 23:59 /RL LIMITED /TN "' + DetachTask + '" /TR "\"' + Copy + '\" ' + Args + '"';
|
||||
if not Exec('schtasks.exe', Cmd, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) or (ResultCode <> 0) then
|
||||
begin
|
||||
Log('detach: schtasks /Create returned ' + IntToStr(ResultCode));
|
||||
Log('detach: schtasks /Create returned ' + IntToStr(ResultCode) + ' (' + LastErrorWords + ') for ' + Cmd);
|
||||
exit;
|
||||
end;
|
||||
if not Exec('schtasks.exe', '/Run /TN "' + DetachTask + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) or (ResultCode <> 0) then
|
||||
begin
|
||||
Log('detach: schtasks /Run returned ' + IntToStr(ResultCode));
|
||||
Log('detach: schtasks /Run returned ' + IntToStr(ResultCode) + ' (' + LastErrorWords + ')');
|
||||
Exec('schtasks.exe', '/Delete /F /TN "' + DetachTask + '"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||
exit;
|
||||
end;
|
||||
|
|
@ -229,11 +275,18 @@ begin
|
|||
Result := True;
|
||||
if UnderAppJob then
|
||||
begin
|
||||
// the detached copy does the install; this process ends here, before any marker or stop step, so the job's tree
|
||||
// teardown finds nothing of the install to kill
|
||||
Result := not RelaunchDetached;
|
||||
if not Result then exit;
|
||||
Log('detach: the detached start failed; installing in place under the job (the stop step will end this process with the engine)');
|
||||
// the detached installer does the install; this process ends here, before any marker or stop step, so the job's tree
|
||||
// teardown finds nothing of the install to kill. When no detached start can be made the install STOPS with the
|
||||
// reason in the log (take 3b, PC 2, 8 October 2026: the in-place fallback under the job ended the engine and died
|
||||
// with it 3 s later, the app down, nothing installed); it never installs in place under a job.
|
||||
if RelaunchDetached then
|
||||
begin
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
Log('REFUSED: this installer runs under the app''s job ' + GetEnv('IGNEUM_JOB_ID') + ' and no detached start could be made (the lines above say why); nothing is installed and the app is left running');
|
||||
Result := False;
|
||||
exit;
|
||||
end;
|
||||
Name := ExtractFileName(ExpandConstant('{srcexe}'));
|
||||
if (Pos('Setup-', Name) > 0) and (Pos('Setup-{#AppVersion}', Name) = 0) then
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@ check() { # <iss file> <ps1 file> -> prints each broken rule, returns 1 when
|
|||
init="$(sed -n '/^function InitializeSetup/,/^end;/p' "$iss")"
|
||||
if ! grep -q "UnderAppJob" <<<"$init" || ! grep -q "RelaunchDetached" <<<"$init"; then echo "rule 6: InitializeSetup does not run the detach before anything else"; bad=1; fi
|
||||
if ! grep -q "RemoveDetachTask" "$iss"; then echo "rule 6: the detached run does not remove its task at ssDone"; bad=1; fi
|
||||
# rule 6b (take 3b, PC 2, 8 October 2026): the copy's OS error is logged, and a job install that cannot detach STOPS with the
|
||||
# reason; it never installs in place under the job (the stop step would end the engine and the job's tree with it)
|
||||
if ! grep -q "SysErrorMessage" "$iss" || ! grep -q "LastErrorWords" "$iss"; then echo "rule 6b: the detach step does not log the OS error of a failed copy or task"; bad=1; fi
|
||||
if grep -q "installing in place under the job" "$iss"; then echo "rule 6b: a job install that cannot detach falls back to installing in place (it must stop with the reason)"; bad=1; fi
|
||||
if ! grep -q "REFUSED: this installer runs under the app''s job" "$iss"; then echo "rule 6b: no REFUSED line for a job install that cannot detach"; bad=1; fi
|
||||
# Inno's Pascal: a routine must be declared before the line that calls it (CurStepChanged calls RemoveDetachTask)
|
||||
local def use
|
||||
def="$(grep -n '^procedure RemoveDetachTask' "$iss" | cut -d: -f1 || true)"; use="$(grep -n '^procedure CurStepChanged' "$iss" | cut -d: -f1 || true)"
|
||||
|
|
@ -66,6 +71,10 @@ ISS
|
|||
grep -v "IGNEUM_JOB_ID\|IGDETACHED\|/Create /F /SC ONCE\|schtasks.exe', '/Run\|UnderAppJob\|RelaunchDetached\|RemoveDetachTask" packaging/windows/Igneum-Miner.iss > "$t/tree.iss"
|
||||
tree_out="$(check "$t/tree.iss" packaging/windows/stop-igneum.ps1 2>/dev/null || true)"
|
||||
if ! grep -q "rule 6" <<<"$tree_out"; then echo "self-test: the job-tree shape passed, it must fail rule 6"; exit 1; fi
|
||||
# the take 3b shape (install-detach-25): a copy that fails with no reason and an in-place fallback under the job
|
||||
{ grep -v "SysErrorMessage\|LastErrorWords\|REFUSED: this installer runs under the app''s job" packaging/windows/Igneum-Miner.iss; echo " Log('detach: the detached start failed; installing in place under the job');"; } > "$t/take3b.iss"
|
||||
t3b_out="$(check "$t/take3b.iss" packaging/windows/stop-igneum.ps1 2>/dev/null || true)"
|
||||
if ! grep -q "rule 6b" <<<"$t3b_out"; then echo "self-test: the take 3b shape passed, it must fail rule 6b"; exit 1; fi
|
||||
echo "installer-stop self-test: tonight's shape is caught, the tree's files pass"
|
||||
exit 0
|
||||
fi
|
||||
|
|
|
|||
Loading…
Reference in a new issue