Repository navigation
Payload Directories
Every payload directory is a flat folder under C:\ProgramData\ManagedState. A file dropped in
one becomes a payload; there is no manifest, no registration and no ordering file.
| Directory | Payload type | Runs as | Elevated | Once | Deleted after run |
|---|---|---|---|---|---|
boot-once |
BootOnce |
Service account (LocalSystem) |
yes | yes | yes, on success |
boot-every |
BootEvery |
Service account (LocalSystem) |
yes | no | no |
login-window |
LoginWindow |
Service account (LocalSystem) |
yes | no | no |
login-once |
LoginOnce |
Console user | no | yes, per user | no |
login-every |
LoginEvery |
Console user | no | no | no |
login-privileged-once |
LoginPrivilegedOnce |
Service account (LocalSystem) |
yes | yes, per machine | no |
login-privileged-every |
LoginPrivilegedEvery |
Service account (LocalSystem) |
yes | no | no |
on-demand |
OnDemand |
Console user | no | no | no |
on-demand-privileged |
OnDemandPrivileged |
Service account (LocalSystem) |
yes | no | no |
"Runs as console user" means StartSet impersonates the interactive session — see
Windows Session Model. Everything else runs in the service's own
LocalSystem context in session 0 (or, when you invoke the CLI by hand, in whatever context you
invoked it from).
The per-machine tracking of login-privileged-once is a deliberate consequence of how the
tracker is selected: the engine uses a per-user ledger only for payload types flagged as user
context (login-once, login-every, on-demand). login-privileged-once is not one of them, so
it is recorded in runonce-system.json and fires once per machine, not once per user. This
differs from outset — see Coming From Outset.
| Path | Contents |
|---|---|
share\ |
Run-once ledgers, checksums.yaml, and a general-purpose shared data directory |
share\runonce-system.json |
Run-once ledger for system-context once payloads |
share\runonce-<username>.json |
Run-once ledger for one user's login-once payloads |
share\checksums.yaml |
Recorded SHA256 checksums, used when checksum_validation is on |
Config.yaml |
Configuration — see Configuration |
logs\ |
Day-nested session logs — see Logging and Reporting |
logs\installs\ |
Verbose msiexec /l*v logs from .msi payloads |
reports\ |
Machine-readable sessions.json, events.json, items.json, run.log
|
Discovery is Directory.GetFiles(directory) — top level only. Subdirectories are not walked.
A script tucked into login-every\MyApp\Setup.ps1 will never run and nothing will report it as
missing; this is the single most common cause of "the package installed but nothing happened".
A file is a payload only if its extension is in allowed_extensions, which defaults to:
| Extension | Handled by |
|---|---|
.ps1 |
PowerShell processor — pwsh if present, otherwise Windows PowerShell |
.cmd, .bat
|
cmd.exe /c |
.exe |
started directly |
.msi |
msiexec /i … /qn /norestart /l*v |
.msix |
Add-AppxPackage -ForceApplicationShutdown |
Anything else in the directory is ignored silently — including .txt notes, .json sidecars and
.psm1 modules. If you need a module alongside a script, keep it outside the payload directory
and load it by absolute path.
Within one directory, payloads run sequentially in case-insensitive alphabetical order by filename. Number your files if order matters:
10-Set-Registry.ps1
20-Map-Drives.ps1
90-Cleanup.ps1
parallel_execution exists as a configuration key but is not implemented; setting it logs a
warning and execution stays sequential.
Across directories, the order is fixed by the trigger — see Architecture.
For boot-once, login-once and login-privileged-once, the engine consults the ledger before
running a payload, and records it afterwards:
- The ledger key is the lowercased filename, not the full path. Moving a script between payload directories does not make it run again.
- Only a successful run is recorded, and
HasExecutedreturns the recordedsuccessvalue — so a payload that failed will be retried on the next trigger. - The recorded SHA256 is compared on every check. Editing a script makes it run again, which is how you re-issue a once payload without touching the ledger.
- A filename listed in
overridesbypasses the check entirely and runs every time. -
boot-oncepayloads are additionally deleted from disk after a successful run.
managedstatekeeper list --show-executed shows the current state; remove --clear-runonce and
remove-override --clear-runonce clear ledger entries. See CLI Reference.
Payloads in an elevated directory (boot-*, login-window, login-privileged-*,
on-demand-privileged) are permission-checked before execution. The file's owner must be one
of:
| Owner | SID |
|---|---|
SYSTEM |
S-1-5-18 |
| The built-in Administrator account | any SID ending -500
|
Administrators |
S-1-5-32-544 |
TrustedInstaller and other service SIDs |
any SID starting S-1-5-80-
|
A file owned by anyone else is skipped with Permission validation failed, which is what stops a
standard user from dropping a script into boot-every and getting SYSTEM execution. Payloads in
user-context directories are only checked for readability.
Ownership, not ACLs, is the test — copying a script into place as an administrator normally satisfies it, but a file extracted from an archive by a standard user will not.
Four sentinel files at the root of C:\ProgramData\ManagedState ask the running service to do
something. The service's FileSystemWatcher matches .startset.* and acts on creation, then
deletes the file.
| File | Effect |
|---|---|
.startset.ondemand |
Run on-demand payloads |
.startset.ondemand-privileged |
Run on-demand-privileged payloads |
.startset.login-privileged |
Allow login-privileged-once payloads to run at the next logon |
.startset.cleanup |
Delete the trigger files |
Content is irrelevant; existence is the signal.
New-Item -ItemType File 'C:\ProgramData\ManagedState\.startset.ondemand' -ForceExisting trigger files are also processed once when the service starts, so one dropped while the service was stopped is not lost.
login-privileged-every runs at every logon with no trigger file needed. Only the -once
half is gated by .startset.login-privileged.
StartSet — MIT licensed — windowsadmins/startset — a Windows port of macadmins/outset.
StartSet
How it works
Migrating
Operating
Contributing