Skip to content

Configuration

Rod Christiansen edited this page Sep 5, 2026 · 2 revisions

Configuration

TaskbarUtil has no settings file of its own — no YAML, no JSON, no environment variables read at runtime. Its entire configuration is the layout XML it builds, plus the registry values it writes to deploy that XML. This page enumerates every path and key the code touches.

Files

Path Written by Purpose
%LOCALAPPDATA%\TaskbarUtil\LayoutModification.xml add, remove, move, replace The layout config. The single source of truth for the pin list
%LOCALAPPDATA%\TaskbarUtil\backup\shortcuts\*.lnk pin backup routine Copies of the user's taskbar shortcuts, restored by reset
%LOCALAPPDATA%\TaskbarUtil\backup\Favorites.bin pin backup routine The Taskband\Favorites binary value as it was before modification
%LOCALAPPDATA%\TaskbarUtil\backup\FavoritesResolve.bin pin backup routine The Taskband\FavoritesResolve binary value
%LOCALAPPDATA%\Microsoft\Windows\Shell\LayoutModification.xml apply fallback Where the layout goes when the policy registry key is not writable
C:\ProgramData\TaskbarUtil\LayoutModification.xml apply --allhomes The shared copy every profile's policy points at
C:\Users\Default\AppData\Local\Microsoft\Windows\Shell\LayoutModification.xml apply --allhomes Seeds the layout for profiles created after this point
C:\ProgramData\ManagedUtilities\logs\<yyyy-MM-dd>\taskbarutil.log every mutating command The human-readable log for that day
C:\ProgramData\ManagedUtilities\logs\<yyyy-MM-dd>\events.jsonl every mutating command The structured event stream for that day, shared with any sibling utility writing into the same root
%LOCALAPPDATA%\TaskbarUtil\logs\<yyyy-MM-dd>\ every mutating command Both of the above, when the shared directory is not writable

Read but never written:

Path Read by
%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar list
%ProgramData%\Microsoft\Windows\Start Menu\Programs app resolution
%APPDATA%\Microsoft\Windows\Start Menu\Programs app resolution

Registry

Policy keys written by apply and cleared by reset

Under HKCU\Software\Policies\Microsoft\Windows\Explorer (and, for --allhomes, the same subpath under HKEY_USERS\<SID>):

Value Type Set to Meaning
StartLayoutFile REG_EXPAND_SZ Path to the layout XML Tells Explorer which layout file to read
LockedStartLayout REG_DWORD 1 Activates the layout. Without it the file is ignored

reset deletes both values, then deletes the key itself if nothing else is left in it.

Caches deleted to force a rebuild

Location Deleted by What it holds
HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband (whole subtree) apply, as part of the Explorer restart Pin order, in binary values
%LOCALAPPDATA%\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\start2.bin apply, as part of the Explorer restart Pin data cache

For --allhomes the same two are cleared per profile, using the profile's own ProfileImagePath for start2.bin and HKEY_USERS\<SID> for Taskband.

Deleting Taskband is why a stale layout does not survive apply, and also why any pin the user added by hand is gone afterwards. There is no partial update.

Taskbar item visibility, written by settings

Under HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, all REG_DWORD:

Setting name Registry value Values
search SearchboxTaskbarMode 0 hidden, 1 icon, 2 icon-label, 3 box
taskview ShowTaskViewButton 0 off, 1 on
widgets TaskbarDa 0 off, 1 on
resume ShowResumeButton 0 off, 1 on
copilot ShowCopilotButton 0 off, 1 on
chat TaskbarMn 0 off, 1 on

Policy values read but never written

settings checks these, in HKLM first and then HKCU, and reports the setting as "locked by policy" if either carries a value. It does not attempt to override them.

Setting Key Value
taskview Software\Policies\Microsoft\Windows\Explorer HideTaskViewButton
widgets SOFTWARE\Policies\Microsoft\Dsh DisableWidgetsBoard
copilot Software\Policies\Microsoft\Windows\WindowsCopilot TurnOffWindowsCopilot
chat Software\Microsoft\Windows\CurrentVersion\Policies\Explorer ChatIcon

Profile enumeration for --allhomes

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList is enumerated to find user profiles. A subkey is considered only if its name starts with S-1-, is not one of the system SIDs S-1-5-18, S-1-5-19 or S-1-5-20, and its ProfileImagePath names a directory that exists. Usernames are resolved from the SID for display only.

Environment variables

None are read at runtime. %ProgramData% and %APPDATA% appear inside generated link paths and are expanded by Explorer, and by the tool when it needs to test whether a shortcut exists — see Layout XML Reference.

build.ps1 reads CERT_THUMBPRINT, TASKBARUTIL_CERT_CN, ENTERPRISE_CERT_CN, TASKBARUTIL_CERT_SUBJECT, ENTERPRISE_CERT_SUBJECT, SIGNTOOL_PATH and SIGNTOOL, but those are build-time only. See Installation.

Logging

Every pin, unpin, move, replace, apply, reset and settings change is appended to the log with its target and outcome, along with any error. Read-only commands (list, find, show) do not log and do not even create the log directory — the log is resolved lazily on first use.

Logs are written into a directory per day, and each entry is written twice: once as a human-readable line in taskbarutil.log, and once as a JSON object in events.jsonl beside it. The day directory is the session — a utility that runs many times a day is invoked too often to justify a directory per run.

Property Value
Primary directory C:\ProgramData\ManagedUtilities\logs\<yyyy-MM-dd>\
Fallback directory %LOCALAPPDATA%\TaskbarUtil\logs\<yyyy-MM-dd>\
Text log taskbarutil.log
Event stream events.jsonl
Line format [yyyy-MM-dd HH:mm:ss] LEVEL message, local time, level padded to five characters
Levels DEBUG, INFO, WARN, ERROR
Encoding UTF-8, no BOM, both files
Roll threshold 5 MB, taskbarutil.log only
Generations kept 5 — taskbarutil.log.1 (newest) through .5, inside the day directory
Retention Day directories older than 30 days are deleted

The day is re-resolved on every entry, so a process still running at midnight continues into the new day's directory rather than the one it started in.

The fallback is chosen by probing whether the shared directory can be created and appended to; an unelevated user typically lands on the per-user path. Log failures are swallowed entirely and never change a command's behaviour or exit code.

The event stream

events.jsonl carries one JSON object per line, with every value a string. Several tools share one stream per day directory, so each record names the tool, the process and the invocation that wrote it — invocation_id is a GUID generated once per process.

Field Meaning
timestamp yyyy-MM-ddTHH:mm:ss.fffzzz, local time with offset
level DEBUG, INFO, WARN or ERROR
event_type error for an ERROR entry, message for everything else
tool taskbarutil
pid Process id, as a string
invocation_id GUID identifying this run
message The same text as the log line

One record, as the writer emits it:

{"timestamp":"2026-09-03T14:05:09.412-07:00","level":"INFO","event_type":"message","tool":"taskbarutil","pid":"7312","invocation_id":"9f2c1d48-6b3a-4f0e-8a71-2d5c4b90e1a3","message":"add: pinned 'Microsoft Edge' (Desktop %ProgramData%\\Microsoft\\Windows\\Start Menu\\Programs\\Microsoft Edge.lnk) at position 3 in C:\\Users\\admin\\AppData\\Local\\TaskbarUtil\\LayoutModification.xml"}

An exception produces two records: an ERROR carrying the exception type and message, then a DEBUG with the full exception text. There is no separate error field.

events.jsonl is not size-rolled — only the text log is. Retention for both is the day directory: on the first entry a process writes, day directories in the log root whose name does not parse as a date within the last 30 days are deleted outright. A directory owned by another account is left alone.

Verbosity

There is no verbosity switch for the file log. It records everything from DEBUG up, and that is not configurable from the command line or a config file.

Console output is not the log. --verbose / -v adds detail to stderr only, and that detail is separate from what is written to the files. --dry-run still writes DEBUG lines describing what would have happened.

Worked example

Build a six-pin office layout and deploy it:

taskbarutil add "File Explorer"
taskbarutil add "Microsoft Edge"
taskbarutil add "Outlook"
taskbarutil add "Microsoft Teams"
taskbarutil add "Calculator"
taskbarutil add "Snipping Tool"

The resulting %LOCALAPPDATA%\TaskbarUtil\LayoutModification.xml:

<?xml version="1.0" encoding="utf-8"?>
<LayoutModificationTemplate Version="1"
    xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification"
    xmlns:defaultlayout="http://schemas.microsoft.com/Start/2014/FullDefaultLayout"
    xmlns:start="http://schemas.microsoft.com/Start/2014/StartLayout"
    xmlns:taskbar="http://schemas.microsoft.com/Start/2014/TaskbarLayout">
  <CustomTaskbarLayoutCollection PinListPlacement="Replace">
    <defaultlayout:TaskbarLayout>
      <taskbar:TaskbarPinList>
        <taskbar:DesktopApp DesktopApplicationID="Microsoft.Windows.Explorer" />
        <taskbar:DesktopApp DesktopApplicationID="MSEdge" />
        <taskbar:UWA AppUserModelID="Microsoft.OutlookForWindows_8wekyb3d8bbwe!Microsoft.OutlookforWindows" />
        <taskbar:UWA AppUserModelID="MSTeams_8wekyb3d8bbwe!MSTeams" />
        <taskbar:UWA AppUserModelID="Microsoft.WindowsCalculator_8wekyb3d8bbwe!App" />
        <taskbar:UWA AppUserModelID="Microsoft.ScreenSketch_8wekyb3d8bbwe!App" />
      </taskbar:TaskbarPinList>
    </defaultlayout:TaskbarLayout>
  </CustomTaskbarLayoutCollection>
</LayoutModificationTemplate>

Then, after taskbarutil apply, the registry state is:

HKCU\Software\Policies\Microsoft\Windows\Explorer
    StartLayoutFile   REG_EXPAND_SZ   C:\Users\<user>\AppData\Local\TaskbarUtil\LayoutModification.xml
    LockedStartLayout REG_DWORD       1

Clone this wiki locally