Repository navigation
Configuration
ManageUsers reads three YAML files and writes one of them. There is no registry
configuration, no environment-variable configuration, and no command-line way to
override a policy value other than --force and --inventory.
| File | Default path | Direction | Purpose |
|---|---|---|---|
Config.yaml |
C:\ProgramData\Management\ManageUsers\Config.yaml |
read | Retention policy, exclusions, admin guard, end-of-term dates |
Sessions.yaml |
C:\ProgramData\Management\ManageUsers\Sessions.yaml |
read/write | Machine-local exclusions and deferred-deletion state |
Inventory.yaml |
C:\ProgramData\Management\Inventory.yaml |
read | Device facts used to select a policy rule. Overridable with --inventory
|
Paths derive from Environment.SpecialFolder.CommonApplicationData and
ProgramFiles, so they follow a relocated %ProgramData% if you have one.
| Constant | Value on a standard install |
|---|---|
| Management root | C:\ProgramData\Management |
| Config directory | C:\ProgramData\Management\ManageUsers |
| Install directory | C:\Program Files\sbin |
| Log directory |
C:\ProgramData\ManagedUsers\logs (operational log and event stream in a <yyyy-MM-dd> subdirectory per day) |
| Log retention | 30 days for day directories; the audit log at the logs root is exempt |
These are compiled in. Nothing about logging is configurable — there is no key for the log directory, the retention window, the rotation size or the log level in any config file, and no environment variable is read for them.
YAML is parsed with YamlDotNet using a null naming convention — keys must be spelled exactly as documented, no case or separator conversion is applied — and unmatched properties are ignored, so a typo'd key is silently dropped rather than raising an error. That is the single most common configuration mistake; verify against the log, not against the file.
| Key | Type | Default | Notes |
|---|---|---|---|
exclusions |
list of strings | [] |
Account names never deleted. Exact, case-insensitive. See Exclusions. |
delete_admins |
bool | false |
false protects every member of the local Administrators group. |
deletable_admins |
list of strings | [] |
Named admins that may be deleted while delete_admins: false. An entry also present in exclusions is dropped. |
policies |
list of rules | [] |
Evaluated in file order, first match wins. |
default_policy |
object | see below | Used when no rule matches. |
end_of_term_dates |
list of month/day
|
[] |
Empty means end-of-term is never true. |
| Key | Type | Default | Notes |
|---|---|---|---|
name |
string | "" |
Logged when the rule matches. Not otherwise used. |
match |
object | empty | See below. A rule with no criteria never matches. |
duration_days |
int | 0 |
Retention threshold. 0 means everything is immediately eligible. Any negative value means never delete. |
strategy |
string | login_and_creation |
creation_only or login_and_creation. Unrecognised values fall back to login_and_creation. |
force_at_end_of_term |
bool | false |
When true and today matches an end-of-term date, the policy becomes an unconditional delete-all. |
Because duration_days defaults to 0, a rule that omits it deletes everything
non-excluded on match. Always state it.
| Key | Type | Compared against |
|---|---|---|
area |
regex string |
Inventory.yaml → area
|
room |
regex string |
Inventory.yaml → location
|
usage |
regex string |
Inventory.yaml → usage
|
- Values are .NET regular expressions evaluated with
RegexOptions.IgnoreCase. - Matching is unanchored — a substring match. Use
^…$for whole-value equality. - Only non-blank criteria are considered, and all of them must match (AND).
- If no criterion is specified, the rule does not match.
| Key | Type | Default | Notes |
|---|---|---|---|
duration_days |
int | 28 |
|
strategy |
string | login_and_creation |
|
force_at_end_of_term |
bool | false |
Parsed but never acted on. The end-of-term branch only exists inside the rule-matching loop; a device on the default policy never force-deletes. |
| Key | Type | Notes |
|---|---|---|
month |
int 1–12 | |
day |
int | The condition is today.Month == month AND today.Day >= day, so a value below the month's length makes a multi-day window. |
| Situation | Result |
|---|---|
Config.yaml missing |
Warning logged. Built-in defaults used: default_policy 28 days / login_and_creation, end-of-term dates 30 Apr, 31 Aug, 31 Dec, no exclusions beyond the built-ins. |
Config.yaml present but policies: empty or absent |
Warning logged. Built-in defaults used for the policy, but exclusions, delete_admins and deletable_admins from your file are preserved. |
Config.yaml fails to parse |
Warning logged with the parser message. Built-in defaults used — including empty exclusions. A malformed file therefore discards your exclusion list. |
That last row is important: a YAML syntax error does not stop the run, it removes
your protection. Validate the file after every change by checking the log line
Loaded N policy rule(s) from Config.yaml.
exclusions:
- svc-admin
- svc-backup
- svc-imaging
- kiosk
delete_admins: false
deletable_admins:
- old-lab-admin
policies:
- name: "Kiosks and drop-in"
match:
area: "^(Kiosk|DropIn)$"
duration_days: 2
strategy: creation_only
force_at_end_of_term: false
- name: "Teaching labs"
match:
area: "Lab"
usage: "^Shared$"
duration_days: 30
strategy: login_and_creation
force_at_end_of_term: true
- name: "Assigned workstations"
match:
usage: "^Assigned$"
duration_days: -1
strategy: login_and_creation
force_at_end_of_term: false
default_policy:
duration_days: 28
strategy: login_and_creation
force_at_end_of_term: false
end_of_term_dates:
- month: 4
day: 30
- month: 8
day: 31
- month: 12
day: 31Reading that: kiosks reap two days after profile creation regardless of use; shared lab machines reap at 30 days of combined inactivity and are emptied on the three end-of-term dates; assigned workstations never reap; anything whose inventory matches none of the three falls to 28 days.
Machine-local state. ManageUsers writes this file, so anything you put in it must survive a rewrite — the serializer emits only the two keys below, so comments and extra keys are lost when the file is saved.
| Key | Type | Purpose |
|---|---|---|
Exclusions |
list of strings | Machine-local additions to the exclusion set. Merged with Config.yaml exclusions. |
DeferredDeletes |
list of strings | Accounts whose deletion was postponed because a session was active. Retried at the start of the next run. Managed by the tool. |
Keys are PascalCase here and snake_case in Config.yaml. That is not a
documentation error; it is how the models are declared.
Exclusions:
- local-svc-account
DeferredDeletes: []The file is rewritten when an account is deferred and when a deferred entry is cleared. If it is missing, a warning is logged and empty defaults are used.
Read-only. Written by whatever provisioning or enrolment system owns device facts; ManageUsers never modifies it.
| Key | Type | Used by ManageUsers |
|---|---|---|
serial |
string | No |
catalog |
string | No |
area |
string |
Yes — policy match.area
|
location |
string |
Yes — policy match.room
|
asset |
string | No |
usage |
string |
Yes — policy match.usage
|
allocation |
string | No |
username |
string | No |
status |
string | No |
platform |
string | No |
All ten keys are modelled, so a file containing all of them parses cleanly; only three influence behaviour. Unmatched keys are ignored.
serial: "0000000000"
catalog: "Production"
area: "Open Lab"
location: "B120"
asset: "IT-00000"
usage: "Shared"
allocation: "Teaching"
status: "Deployed"
platform: "Windows"If the file is missing, a warning is logged and every field is empty — which
means no rule with criteria can match and the device uses default_policy.
Override the path per invocation:
& 'C:\Program Files\sbin\manageusers.exe' --simulate --inventory 'D:\Config\inventory.yaml'There is no way to override the Config.yaml or Sessions.yaml paths.
The application reads none. Two are used by the build and packaging scripts only, and are documented in Development:
| Variable | Used by | Purpose |
|---|---|---|
PACKAGE_ID_PREFIX |
cimipkg at package time |
Package identifier prefix |
PACKAGE_DEVELOPER |
cimipkg at package time |
Package developer string |
SIGNING_CERT_SUBJECT |
build.ps1 |
Preferred code-signing certificate subject |
ManageUsers reads and writes the registry, but not for its own configuration:
| Key | Access | Purpose |
|---|---|---|
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList |
read/delete | Profile enumeration; per-SID subkey removal on profile deletion |
HKEY_USERS\<SID> |
read | In-use detection (loaded hive) |
HKLM\SOFTWARE\Microsoft\IdentityStore\Cache |
read | Enumerated and logged during account deletion; nothing is written |
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList |
create/write | Every excluded account name is written as DWORD 0, hiding it from the sign-in screen. Entries are never removed. |
That last one is a side effect people do not expect: adding a name to
exclusions: also hides it from the Windows sign-in screen, on the next run,
permanently. The five built-in accounts are skipped since Windows already hides
them. To un-hide an account, remove its value from that key by hand.
- Selection Logic — how these values are actually applied
- Exclusions — matching semantics
- Safe Deployment — what to set before the first run
ManageUsers — local account and profile retention for shared Windows devices · source repository · see the repository for license terms
Before you deploy
Reference
Internals
Help
This tool deletes user
accounts and profiles.
Run --simulate first.