-
Notifications
You must be signed in to change notification settings - Fork 37
Lich Character Watchdog ‐ Windows
A PowerShell-based watchdog that ensures a specific Lich character session stays running on Windows. Detects whether the character is currently active using two signals (session file + process check) and relaunches Lich if either is missing. Scheduled via Task Scheduler.
Note
Linux and macOS instructions live on separate wiki pages:
- How it works
- The script
- Configuration
- Task Scheduler setup
- Testing
- Troubleshooting
- Running multiple characters
The watchdog considers a character "running" only if both of these are true:
-
Session file present — Lich writes
%TEMP%\simutronics\sessions\<CharacterName>.sessionwhile connected. -
Matching process alive — A
rubyw.exeprocess exists whose command line referenceslichand--login <CharacterName>. If either signal is missing, the watchdog launches Lich with the configured arguments.
| Scenario | Session file | Process | Watchdog action |
|---|---|---|---|
| Normal running session | ✅ | ✅ | Do nothing |
| Clean disconnect | ❌ | ❌ | Relaunch |
| Lich crashed hard (stale session file) | ✅ | ❌ | Relaunch |
| Lich starting up (process before session) | ❌ | ✅ | Relaunch* |
Note
The startup race window is small; with a 10-minute schedule it's very unlikely to trigger a duplicate launch. If you see duplicate launches in the log, that's the cause.
Save this as C:\Lich5\watchdog.ps1 (or wherever you prefer).
<#
.SYNOPSIS
Ensures a specific Lich character session is running. Launches if not.
.DESCRIPTION
Considers the character "running" only if BOTH are true:
1. Lich's session file exists at %TEMP%\simutronics\sessions\<Char>.session
2. A rubyw.exe process is alive whose command line references lich + --login <Char>
Designed to run on a recurring schedule via Task Scheduler.
#>
# ---- Config ----------------------------------------------------------------
$CharacterName = 'Mycharname'
$RubyExe = 'C:\Ruby34-x64\bin\rubyw.exe'
$LichDir = 'C:\Lich5'
$LichScript = 'lich.rbw'
$LichArgs = @('--login', $CharacterName, '--gemstone', '--wizard')
$LogFile = 'C:\Lich5\logs\watchdog.log'
$SessionFile = Join-Path $env:TEMP "simutronics\sessions\$CharacterName.session"
# ---------------------------------------------------------------------------
function Write-Log {
param([string]$Message)
$stamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
$line = "[$stamp] $Message"
try {
$dir = Split-Path -Parent $LogFile
if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
Add-Content -Path $LogFile -Value $line
} catch { }
}
function Test-SessionFile {
param([string]$Path)
Test-Path -LiteralPath $Path
}
function Test-LichProcess {
param([string]$Character)
# Match rubyw.exe whose command line references lich AND --login <Character>.
# Case-insensitive; tolerates either "--login Name" or "--login=Name".
$escaped = [regex]::Escape($Character)
$pattern = "(?i)lich.*--login[\s=]+$escaped\b"
$procs = Get-CimInstance Win32_Process -Filter "Name = 'rubyw.exe'" -ErrorAction SilentlyContinue |
Where-Object { $_.CommandLine -and $_.CommandLine -match $pattern }
return [bool]$procs
}
try {
$sessionOk = Test-SessionFile -Path $SessionFile
$processOk = Test-LichProcess -Character $CharacterName
if ($sessionOk -and $processOk) {
Write-Log "OK: $CharacterName running (session file + process both present)."
exit 0
}
# Log which check failed, useful for diagnosing flapping
$reason = @()
if (-not $sessionOk) { $reason += 'no session file' }
if (-not $processOk) { $reason += 'no matching rubyw.exe' }
Write-Log "Not running for $CharacterName ($($reason -join ', ')). Launching..."
if (-not (Test-Path $RubyExe)) {
Write-Log "ERROR: rubyw.exe not found at $RubyExe"; exit 2
}
if (-not (Test-Path (Join-Path $LichDir $LichScript))) {
Write-Log "ERROR: $LichScript not found in $LichDir"; exit 2
}
$allArgs = @($LichScript) + $LichArgs
Start-Process -FilePath $RubyExe `
-ArgumentList $allArgs `
-WorkingDirectory $LichDir | Out-Null
Write-Log "Launched: $RubyExe $($allArgs -join ' ')"
exit 0
}
catch {
Write-Log "ERROR: $($_.Exception.Message)"
exit 1
}Edit the variables at the top of the script:
| Variable | Description | Example |
|---|---|---|
$CharacterName |
Character name as it appears in --login
|
'Mycharname' |
$RubyExe |
Full path to rubyw.exe
|
'C:\Ruby34-x64\bin\rubyw.exe' |
$LichDir |
Lich install directory | 'C:\Lich5' |
$LichScript |
Lich entry script | 'lich.rbw' |
$LichArgs |
Launch arguments (must match how you normally launch) | @('--login', $CharacterName, '--gemstone', '--wizard') |
$LogFile |
Where to write watchdog activity | 'C:\Lich5\logs\watchdog.log' |
Before scheduling, launch Lich the normal way for your character, then run this from a PowerShell window:
Get-CimInstance Win32_Process -Filter "Name = 'rubyw.exe'" |
Select-Object ProcessId, CommandLine | Format-ListLook at the actual CommandLine. The regex (?i)lich.*--login[\s=]+<name>\b expects something like:
- ✅
... lich.rbw --login Mycharname --gemstone --wizard - ✅
... lich.rbw --login=Mycharname ... - ❌
... rubyw.exe lich.rbw --login "Mycharname" ...(quoted name won't match) If your real command quotes the name, change the pattern inTest-LichProcessfrom--login[\s=]+$escaped\bto--login[\s=]+"?$escaped"?\b.
- Open Task Scheduler (
taskschd.msc). - In the right pane, click Create Task... (not "Create Basic Task" — you need the full dialog).
-
Name:
Lich Watchdog - Mycharname(or similar) - Description: (optional) "Restarts Lich for Mycharname if it stops running"
-
Security options:
- Select Run only when user is logged on — required, because WizardFE needs an interactive desktop
- Leave Run with highest privileges unchecked unless your Lich install specifically requires it
Click New... and configure:
-
Begin the task:
At log on - Specific user: your user account
-
Advanced settings:
- Check Repeat task every:
10 minutes -
for a duration of:
Indefinitely - Check Enabled Click OK.
- Check Repeat task every:
Tip
"10 minutes" isn't in the default dropdown. Type it directly into the field — Task Scheduler accepts custom intervals like 10 minutes, 15 minutes, etc.
Click New... and configure:
-
Action:
Start a program -
Program/script:
powershell.exe -
Add arguments:
-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File "C:\Lich5\watchdog.ps1" -
Start in: (leave blank —
Start-Processuses-WorkingDirectoryexplicitly) Click OK.
- Uncheck Start the task only if the computer is on AC power if you're on a laptop and want it to run on battery too.
- Leave the rest at defaults.
- Check Allow task to be run on demand
- Check If the running task does not end when requested, force it to stop
-
If the task is already running, the following rule applies:
Do not start a new instance— important, prevents overlapping runs from stacking - Leave other defaults Click OK to save the task. You may be prompted for your Windows password.
Before trusting the schedule, verify all four scenarios behave correctly. Run the script manually each time with:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Lich5\watchdog.ps1"Then check C:\Lich5\logs\watchdog.log for the result.
| # | Setup | Expected log line | Expected behavior |
|---|---|---|---|
| 1 | Lich already running for the character | OK: ... both present |
No relaunch |
| 2 | Lich cleanly exited (no process, no session file) | Not running (no session file, no matching rubyw.exe) |
Relaunch |
| 3 | Kill rubyw.exe from Task Manager (stale session file remains) |
Not running (no matching rubyw.exe) |
Relaunch |
| 4 | Delete the session file manually but leave process running | Not running (no session file) |
Relaunch* |
Warning
Scenario 4 will cause a duplicate launch, which is the expected tradeoff for catching scenario 3.
After creating the task, right-click it in Task Scheduler and choose Run to fire it immediately. Check the History tab and the watchdog log to confirm it executed cleanly.
Log file isn't being created
The script tries to create the log directory but the user account running the task needs write permission to the parent directory. If `C:\Lich5\logs\` doesn't appear, check permissions or change `$LogFile` to somewhere under your user profile (e.g., `"$env:USERPROFILE\lich-watchdog.log"`).Watchdog always relaunches even though Lich is running
The process regex isn't matching your real command line. Run the `Get-CimInstance` diagnostic shown above, look at the actual `CommandLine`, and adjust the pattern in `Test-LichProcess` to match.Watchdog never relaunches even though Lich is dead
Most likely `$env:TEMP` isn't resolving to the location Lich uses. The script assumes the task runs as your interactive user (which is why "Run only when user is logged on" matters). If you ever switch to "Run whether user is logged on or not" or run as SYSTEM, `$env:TEMP` becomes `C:\Windows\Temp` and the session-file check will always fail. Add a diagnostic line near the top of the script to confirm:Write-Log "Looking for session file at: $SessionFile"Task runs but no window appears
The task is probably configured with "Run whether user is logged on or not" — switch to "Run only when user is logged on" so the launched WizardFE has a desktop to draw on.Multiple Lich instances spawn
Either (a) the regex isn't matching your real command line so it thinks nothing is running, or (b) you hit the startup race window where the process was alive but the session file wasn't written yet. The log will tell you which: look for "no matching rubyw.exe" (case a) vs "no session file" (case b).To watchdog more than one character, make a copy of the script per character (watchdog-charA.ps1, watchdog-charB.ps1), edit $CharacterName and $LichArgs in each, and create a separate scheduled task pointing to each script. The process regex matches on the specific character name, so they won't interfere with each other.