f0ce286527
Build backend images / build content-svc (push) Failing after 54s
Build backend images / build file-svc (push) Failing after 56s
Build backend images / build gateway (push) Failing after 57s
Build backend images / build identity-svc (push) Failing after 58s
Build backend images / build notification-svc (push) Failing after 1m4s
Build backend images / build render-svc (push) Failing after 2m27s
Build backend images / build studio-svc (push) Failing after 55s
PrepareFreshAE = taskkill AfterFX/aerender/AfterFXLib/dynamiclinkmanager/QT32 + 2s settle + clear crash markers, then launch. A hung/zombie AE from a prior job would otherwise block or corrupt the new run. RunScan now calls it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
61 lines
2.1 KiB
Go
61 lines
2.1 KiB
Go
package runner
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"time"
|
|
)
|
|
|
|
// aeProcesses are the AE-related executables to force-kill before a fresh launch.
|
|
var aeProcesses = []string{
|
|
"AfterFX.exe", // the AE app
|
|
"aerender.exe", // the headless renderer
|
|
"AfterFXLib.exe", // AE render engine
|
|
"dynamiclinkmanager.exe", // Dynamic Link
|
|
"Adobe QT32 Server.exe", // QuickTime/media server
|
|
}
|
|
|
|
// PrepareFreshAE guarantees a clean AE start before a scan/render: it force-kills
|
|
// any leftover AE process (a hung/zombie instance from a prior job would otherwise
|
|
// block or corrupt the new launch), waits for them to release file locks, then
|
|
// clears the crash/Safe-Mode markers. Call this right before launching afterfx/aerender.
|
|
func PrepareFreshAE() {
|
|
if os.Getenv("APPDATA") == "" {
|
|
return // non-Windows / dev
|
|
}
|
|
KillAEProcesses()
|
|
time.Sleep(2 * time.Second) // let the OS reap processes + release locks
|
|
ClearAECrashState()
|
|
}
|
|
|
|
// KillAEProcesses force-terminates every AE-related process tree (taskkill is a
|
|
// Windows built-in — no external dep). Errors (e.g. "process not found") are ignored.
|
|
func KillAEProcesses() {
|
|
for _, name := range aeProcesses {
|
|
_ = exec.Command("taskkill", "/F", "/T", "/IM", name).Run()
|
|
}
|
|
}
|
|
|
|
// ClearAECrashState removes the markers After Effects uses to decide it crashed,
|
|
// so the blocking "Crash Repair Options" (Safe Mode) dialog never appears:
|
|
// 1. SCRPriorState.json in each AE prefs version dir (session crash-recovery state).
|
|
// 2. HKCU\Software\Adobe\After Effects\AppStates — a leftover per-session GUID
|
|
// (after a kill/crash) trips Safe Mode. reg.exe is a Windows built-in.
|
|
// Targeted (vs. wiping all prefs) so the node keeps its AE preferences.
|
|
func ClearAECrashState() {
|
|
appData := os.Getenv("APPDATA")
|
|
if appData == "" {
|
|
return
|
|
}
|
|
base := filepath.Join(appData, "Adobe", "After Effects")
|
|
if entries, err := os.ReadDir(base); err == nil {
|
|
for _, e := range entries {
|
|
if e.IsDir() {
|
|
_ = os.Remove(filepath.Join(base, e.Name(), "SCRPriorState.json"))
|
|
}
|
|
}
|
|
}
|
|
_ = exec.Command("reg", "delete", `HKCU\Software\Adobe\After Effects\AppStates`, "/f").Run()
|
|
}
|