Skip to content

[Unpackaged] Fix taskbar glomming due to AUMID#20064

Open
carlos-zamora wants to merge 3 commits intomainfrom
dev/cazamor/bugfix/aumid
Open

[Unpackaged] Fix taskbar glomming due to AUMID#20064
carlos-zamora wants to merge 3 commits intomainfrom
dev/cazamor/bugfix/aumid

Conversation

@carlos-zamora
Copy link
Copy Markdown
Member

Summary of the Pull Request

The bug was caused by an AUMID mismatch between the Taskbar's .lnk file and Windows Terminal. Since no AUMID was associated with the .exe, the OS automatically creates one for us. However, #20018 added an AUMID for unpackaged scenarios, so now there was a mismatch, resulting in a new taskbar entry being created.

To fix this, we check if a .lnk points to our .exe in the taskbar. There's 3 cases here:

  1. no .lnk of interest exists --> set the AUMID normally
  2. the .lnk carries our AUMID --> set the AUMID normally
  3. the .lnk doesn't have an AUMID (aka uses the auto-resolved one) -->
    • for this launch: don't set the AUMID so that we both use the auto-resolved one
    • on next launch: set the AUMID on the .lnk and process so that they all agree

Validation Steps Performed

In unpackaged folder, move WindowsTerminal.exe to the taskbar (creates .lnk)...
✅ Double-click the .exe --> Same taskbar entry is used
✅ Double-click the .exe again --> second window goes to same taskbar entry

The first window doesn't have to close for this to work. It just * works *!

Bug introduced in #20018
Closes #20053

@carlos-zamora carlos-zamora requested a review from DHowett April 3, 2026 22:06
Comment thread src/cascadia/WindowsTerminal/WindowEmperor.cpp Fixed
@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Member

@lhecker lhecker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat code! One minor bug only.

Comment on lines +318 to +323
// GH#20053: The shell resolves taskbar grouping identity as: per-window AUMID >
// per-process AUMID > auto-derived from exe path. Before we started setting a
// process AUMID, both the pinned .lnk and the process used auto-derived
// identity, so they matched. Now that we set an explicit AUMID, a pinned .lnk
// that predates the AUMID change has no AUMID and still uses auto-derived
// identity, causing a mismatch and a duplicate taskbar button.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So LNK files essentially... cache? the AUMID that an app sets? Is that right?
So if my app ever changes the ID all LNKs are invalid?

Comment on lines +328 to +330
// AUMID for THIS launch (both sides use auto-derived identity, so they match)
// and defer stamping the shortcut to process exit. On the next launch, the pin
// has our AUMID, so we set the process AUMID to match, and both agree.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not update the LNK immediately?

LR"(%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\*.lnk)");

WIN32_FIND_DATAW findData{};
const wil::unique_hfind findHandle{ FindFirstFileW(taskbarGlob.c_str(), &findData) };
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using

FindFirstFileEx(taskbarGlob.c_str(), FindExInfoBasic, &findData, FindExSearchNameMatch, NULL, FIND_FIRST_EX_LARGE_FETCH);

This does two things:

  • FindExInfoBasic avoids 8.3 short name conversion (sometimes expensive to calculate)
  • FIND_FIRST_EX_LARGE_FETCH allocates larger buffers (the default is more appropriate for DOS times)

continue;
}

if (_wcsicmp(targetPath, ourExePath.c_str()) != 0)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_wcsicmp uses CompareStringW and is for linguistic / human comparisons. Here you want CompareStringOrdinal for machine-style comparisons. You can use til::compare_ordinal_insensitive for that or call CompareStringOrdinal directly. Both are just as readable IMO.

@microsoft-github-policy-service microsoft-github-policy-service Bot added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Apr 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something zBugBash-Consider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Regression Canary] Problem start WT with lnk

3 participants