Skip to content

Layout XML Reference

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

Layout XML Reference

The layout config is a Microsoft LayoutModificationTemplate document. TaskbarUtil both generates and parses it, and it is a plain file you can read, diff, version-control and hand-edit. It is the closest thing this tool has to dockutil's com.apple.dock.plist, with the crucial difference that Explorer treats it as policy input rather than as its live state.

Document shape

<?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:TaskbarPinList>
    </defaultlayout:TaskbarLayout>
  </CustomTaskbarLayoutCollection>
</LayoutModificationTemplate>

Namespaces

Prefix URI
default http://schemas.microsoft.com/Start/2014/LayoutModification
defaultlayout http://schemas.microsoft.com/Start/2014/FullDefaultLayout
start http://schemas.microsoft.com/Start/2014/StartLayout
taskbar http://schemas.microsoft.com/Start/2014/TaskbarLayout

All four are declared on the root element. start is declared but unused by the taskbar pin list — it is part of the template's canonical namespace set and is kept for compatibility with the Start-menu half of the schema, which TaskbarUtil does not write.

Version="1"

Required. Without this attribute on LayoutModificationTemplate, Windows silently ignores the entire file — no error, no event, no partial application, just a stock taskbar. If you hand-author a layout and it appears to do nothing, check this first.

PinListPlacement="Replace"

TaskbarUtil always writes Replace. This is why the layout is all-or-nothing: the pin list in the file becomes the complete taskbar, and anything the user had pinned is gone after apply. The schema also permits Append, but nothing in TaskbarUtil emits it and nothing reads it back.

PinGeneration="1"

Emitted on CustomTaskbarLayoutCollection only when the layout's AllowUserUnpin flag is set. It is parsed back from the file and reported by show.

There is no CLI flag that sets it. The only way to turn it on is to hand-edit the XML and add the attribute, which the parser will then preserve on subsequent add/remove/move/replace rewrites. If you need users to be able to unpin what you deployed, this is the lever.

Pin element types

The TaskbarPinList holds an ordered list of pins. Order in the file is order on the taskbar. Three element shapes are produced and recognised:

Element Attribute Used for Example
taskbar:DesktopApp DesktopApplicationLinkPath A classic desktop app, identified by its Start Menu shortcut %ProgramData%\Microsoft\Windows\Start Menu\Programs\Google Chrome.lnk
taskbar:DesktopApp DesktopApplicationID A shell-registered application identifier Microsoft.Windows.Explorer
taskbar:UWA AppUserModelID A UWP / MSIX / Store app Microsoft.WindowsTerminal_8wekyb3d8bbwe!App

When a pin carries both a link path and an application ID, the link path wins. A pin with neither degrades to a DesktopApp whose DesktopApplicationLinkPath is whatever identifier the pin does have — which will not resolve, and is worth catching with show before you deploy.

Portable link paths

Shortcut paths are rewritten to environment-variable form before they go into the XML, so one layout works across machines and users:

Actual location Written as
All-users Start Menu %ProgramData%\Microsoft\Windows\Start Menu\...
Per-user Start Menu %APPDATA%\Microsoft\Windows\Start Menu\...
Anywhere else the literal path, unchanged

A per-user (%APPDATA%) path is a trap for fleet deployment: the layout will only work for users who happen to have that shortcut in their own profile. Prefer apps installed machine-wide, whose shortcuts land under %ProgramData%. Check with taskbarutil show before rolling a layout out to anyone else.

Parsing rules

When TaskbarUtil reads a layout back it takes the first CustomTaskbarLayoutCollection and the first TaskbarPinList it finds anywhere in the document, so a file with several of either is read only for its first. Elements inside the pin list that are neither UWA nor DesktopApp, and elements missing the attribute their type requires, are skipped silently.

Display names are not stored in the XML — the schema has nowhere to put them. On read they are reconstructed:

  1. Match the identifier against the built-in known-apps table and use its friendly name.
  2. For a link path, use the shortcut's file name without extension.
  3. For an application ID or AUMID, take the text after the last ., then before the first _, then before the first !. Microsoft.WindowsTerminal_8wekyb3d8bbwe!App becomes WindowsTerminal.

This is why a pin can show a slightly different name after a round-trip than the one you typed into add. The identifier — the thing that actually matters — is unchanged.

Hand-editing

The file is safe to edit by hand, and doing so is the supported route to the two things the CLI cannot express: PinGeneration="1", and pin identifiers the resolver will not produce. Rewrite it, then run taskbarutil show to confirm it parses and taskbarutil apply to deploy.

Anything the parser does not understand is dropped on the next add, remove, move or replace, because those commands parse the file into the in-memory model and regenerate it from scratch. If you hand-author something exotic, either keep it out of the mutating commands' way or keep a pristine copy under version control and deploy it directly by pointing StartLayoutFile at it.

Validating a layout

There is no schema-validation command. The practical checks:

taskbarutil show

If the pin count and identifiers look right, the XML parsed. If show reports the config as empty when the file is not, either Version="1" is missing, a namespace is wrong, or the pin elements are not in a recognised TaskbarPinList.

taskbarutil apply --dry-run

This lists each pin with its type without writing policy or restarting the shell.

Clone this wiki locally