Skip to content

Command File Reference

Rod Christiansen edited this page Sep 3, 2026 · 1 revision

Command File Reference

The command file is how a script talks to a dialog that is already on screen. It is the same idea as swiftDialog's command file, and the syntax is deliberately close enough that most swiftDialog command lines transfer unchanged.

Enable it with --commandfile <path>. The dialog creates the file and any missing parent directories if they do not exist, then watches it.

How the file is read

Aspect Behaviour
Transport Append lines to the file. One command per line
Encoding UTF-8, read without a BOM assumption. Write with -Encoding UTF8 from PowerShell
Sharing Opened FileShare.ReadWrite, so the writer never needs to close between appends
Trigger A FileSystemWatcher on last-write and size, debounced by 100 ms
Position The dialog tracks a byte offset and only reads what was appended since the last pass. Rewriting or truncating the file mid-run desynchronises this — always append
Startup Monitoring begins ~1 s after the window is created and starts reading at offset 0, so lines written before launch are still applied
Blank lines Skipped
Comments A line beginning with # is skipped
Unknown verbs Silently ignored, no error, no log entry visible to the caller

Because reading is offset-based, a script that wants to reuse the same path across runs should delete the file before launching the dialog rather than clearing it while one is open.

Syntax

verb: value

The verb is everything before the first colon, trimmed and lowercased. The value is everything after it, trimmed. A bare verb with no colon is accepted for value-less commands, which is why quit works on its own.

Compound commands (listitem) take a comma-separated list of key: value pairs inside the value. Keys are lowercased; a value wrapped in double quotes has the quotes stripped.

Verbs applied by the dialog window

These are the commands the shipped dialog.exe window actually acts on.

Command Value Effect
title: <text> any text Replaces the header text
message: <text> any text Replaces the body text
progress: <n> integer Sets the progress bar value. The bar's maximum is fixed at 100, so this is a percentage. A non-integer value is ignored
progresstext: <text> any text Replaces the caption above the progress bar
button1text: <text> any text Replaces the button's label
button1: enable Enables the button and releases the close lock set by --button1disabled
button1: disable Disables the button and engages the close lock, even if --button1disabled was not passed at launch
listitem: … see below Adds or updates a list row
quit Closes the dialog. The process exits 0

listitem

The listitem verb both adds and updates rows. The action is update unless an add or delete action is given.

listitem: add, title: Google Chrome, status: wait, statustext: Queued
listitem: update, title: Google Chrome, status: pending, statustext: Installing...
listitem: update, title: Google Chrome, status: success, statustext: Installed

Parameters

Key Applies to Meaning
title add, update The row's text, and the key rows are looked up by on update. Must match exactly, including case and spacing
status add, update none, wait, success, fail, error, pending, progress. Sets the indicator; pending and progress animate a spinner
statustext add, update The right-hand secondary text. New rows start at Pending
index update 0-based row index, used to find the row when title is not supplied or does not match

Action forms

All of these select the add action; the parser accepts each because scripts in the wild use each:

listitem: add, title: Chrome, status: wait
listitem: action: add, title: Chrome, status: wait

An update action is what you get by default, so the shorter form is fine:

listitem: title: Chrome, status: success

Limitations to design around

  • delete is parsed but not implemented. A listitem: delete, … command is accepted, falls through to the update branch, finds nothing to change, and does nothing. Rows cannot be removed from a running dialog.
  • Rows are keyed by title, in a dictionary. Adding two rows with the same title leaves the tracker pointing at the second one; the first row stays on screen but can no longer be updated by title. Use unique titles, or update by index.
  • A title containing a comma cannot be expressed. The parameter splitter breaks on every comma, so title: Acrobat, Reader parses as title: Acrobat plus a junk parameter.
  • Updating an unknown title is a silent no-op. If nothing changes on screen, the first thing to check is an exact title match against the add that created the row.
  • list: clear is parsed into an action but the window has no handler for the list verb, so it does nothing. There is no way to clear the list from the command file.

Verbs the parser accepts but the window ignores

These pass validation — the parser will not reject the line — but the shipped GUI has no case for them, so nothing happens. They exist because the console front end and the unfinished service layer understand them.

Command Status
progressincrement: <n> Handled only by the console front end. No effect on the window; add to the current value yourself and send progress:
progressreset Same — send progress: 0 instead
list: clear No window handler
config: <json> The JSON configuration model exists but the window's loader returns false unconditionally. No effect
style: <json> No effect
theme: <name> No effect. The four built-in themes (corporate, dark, modern, enterprise) are not reachable from a running dialog
execute: <cmd> No effect from the window. Shell execution is implemented in the core library but the window's implementation is a stub returning an empty result
executepowershell: <script> Same
executeoutput: <cmd> Same
width: <n>, height: <n>, position: <p> In the valid-verb list; no window handler
icon: <path>, image: <path> In the valid-verb list; no window handler
button2text: <text>, button2: <state> In the valid-verb list; the window has no second button

If you need any of these behaviours today, do them in the controlling script and reflect the result into the dialog with title:, message:, progress: and listitem:.

Worked example

Writing the whole conversation with the dialog from PowerShell:

$commandFile = "$env:ProgramData\ManagedNotifications\work\setup.txt"
New-Item -ItemType Directory -Path (Split-Path $commandFile) -Force | Out-Null
Remove-Item $commandFile -Force -ErrorAction SilentlyContinue

$dialog = Start-Process dialog -PassThru -ArgumentList @(
    "--window", "--progress",
    "--title", "Preparing this computer",
    "--message", "Leave this window open until it closes itself.",
    "--commandfile", $commandFile
)

Start-Sleep -Seconds 2

$steps = "Baseline policy", "Endpoint agent", "Printer queues"
foreach ($step in $steps) {
    Add-Content $commandFile "listitem: add, title: $step, status: wait, statustext: Queued" -Encoding UTF8
}

$done = 0
foreach ($step in $steps) {
    Add-Content $commandFile "listitem: update, title: $step, status: pending, statustext: Working" -Encoding UTF8
    Add-Content $commandFile "progresstext: $step" -Encoding UTF8

    Start-Sleep -Seconds 3

    $done++
    Add-Content $commandFile "listitem: update, title: $step, status: success, statustext: Done" -Encoding UTF8
    Add-Content $commandFile "progress: $([math]::Round($done / $steps.Count * 100))" -Encoding UTF8
}

Add-Content $commandFile "message: This computer is ready." -Encoding UTF8
Add-Content $commandFile "button1: enable" -Encoding UTF8
Add-Content $commandFile "quit" -Encoding UTF8

Wait-Process -Id $dialog.Id -Timeout 15 -ErrorAction SilentlyContinue
Remove-Item $commandFile -Force -ErrorAction SilentlyContinue

More patterns, including the locked-window form, are in Recipes.

Clone this wiki locally