jobrun: a refused, cancelled or timed-out administrator prompt fails the job (exit 251)
The elevated launcher exited 0 after Windows cancelled an unanswered UAC prompt at 122 s (PC 1 driver job, 5 October 2026), so the job read as done. Start-Process now runs under -ErrorAction Stop in a try/catch, a missing process is exit 251, and the summary says what to do. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
7d09857f91
commit
574eacc265
1 changed files with 19 additions and 1 deletions
|
|
@ -1119,7 +1119,10 @@ fn run_script(shared: &Arc<Shared>, job: &Job, sink: &Sink, jobs_dir: &Path, dat
|
|||
std::fs::write(&wrapper, [b"\xEF\xBB\xBF".as_slice(), w.as_bytes()].concat()).map_err(|e| e.to_string())?;
|
||||
let _ = std::fs::remove_file(&out_file);
|
||||
let inner = format!("-NoProfile -ExecutionPolicy Bypass -File \"{}\"", wrapper.display());
|
||||
let ps = format!("$p = Start-Process -FilePath powershell.exe -ArgumentList '{}' -Verb RunAs -Wait -WindowStyle Hidden -PassThru; exit $p.ExitCode", inner.replace('\'', "''"));
|
||||
// A refused or unanswered UAC prompt makes Start-Process throw (`$p` stays null) and `exit $p.ExitCode`
|
||||
// would exit 0: the 5 October 2026 driver job on PC 1 was reported "done" after Windows cancelled its
|
||||
// prompt at 122 s. The launch failure is exit 251 and says so on stderr.
|
||||
let ps = format!("try {{ $p = Start-Process -FilePath powershell.exe -ArgumentList '{}' -Verb RunAs -Wait -WindowStyle Hidden -PassThru -ErrorAction Stop }} catch {{ Write-Error ('elevated launch failed (UAC refused, cancelled or timed out): ' + $_.Exception.Message); exit 251 }}; if ($null -eq $p) {{ Write-Error 'elevated launch failed: no process'; exit 251 }}; exit $p.ExitCode", inner.replace('\'', "''"));
|
||||
cmd = Command::new(crate::platform::tool("powershell"));
|
||||
cmd.args(["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", &ps]);
|
||||
} else if shell == "powershell" {
|
||||
|
|
@ -1145,6 +1148,7 @@ fn run_script(shared: &Arc<Shared>, job: &Job, sink: &Sink, jobs_dir: &Path, dat
|
|||
fn finish_ran(ran: Ran, what: &str) -> Result<Done, String> {
|
||||
match ran.code {
|
||||
Some(0) => Ok(Done { status: "done".into(), exit: 0, summary: format!("{what} finished, exit 0"), extra: json!({}) }),
|
||||
Some(251) => Ok(Done { status: "failed".into(), exit: 251, summary: format!("{what} did not start: the administrator prompt was refused, cancelled or timed out (click Yes within 2 minutes)"), extra: json!({}) }),
|
||||
Some(c) => Ok(Done { status: "failed".into(), exit: c as i64, summary: format!("{what} exited with code {c}"), extra: json!({}) }),
|
||||
None if ran.timed_out => Ok(Done { status: "timeout".into(), exit: -1, summary: format!("{what} hit the time cap and was ended"), extra: json!({}) }),
|
||||
None => Err(format!("{what} was ended")),
|
||||
|
|
@ -1259,6 +1263,20 @@ fn collect_done(uploaded: u32, failed: u32, names: Vec<String>, ran: Option<Ran>
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn a_refused_administrator_prompt_is_a_failure_not_done() {
|
||||
// 5 October 2026: the elevated launcher exited 0 after Windows cancelled an unanswered UAC prompt
|
||||
let d = finish_ran(Ran { code: Some(251), timed_out: false }, "script").unwrap();
|
||||
assert_eq!((d.status.as_str(), d.exit), ("failed", 251));
|
||||
assert!(d.summary.contains("administrator prompt"), "{}", d.summary);
|
||||
let d = finish_ran(Ran { code: Some(0), timed_out: false }, "script").unwrap();
|
||||
assert_eq!(d.status, "done");
|
||||
// the launcher string itself: a thrown Start-Process must not fall through to `exit $p.ExitCode`
|
||||
let src = include_str!("jobrun.rs");
|
||||
assert!(src.contains("-Verb RunAs -Wait -WindowStyle Hidden -PassThru -ErrorAction Stop }} catch {{"));
|
||||
assert!(src.contains("if ($null -eq $p) {{ Write-Error 'elevated launch failed: no process'; exit 251 }}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_outcome_follows_the_command_exit() {
|
||||
let d = collect_done(0, 0, vec![], None);
|
||||
|
|
|
|||
Loading…
Reference in a new issue