+- **Windows Performance Analyzer is not part of Visual Studio.** VS has its own
+ Performance Profiler, which is a different, `.diagsession`-based tool and
+ cannot open an `.etl`. WPA ships with `xperf` and `wpr` in the Windows
+ Performance Toolkit, which exists in exactly two places: as an optional
+ *feature* of the Windows SDK (`OptionId.WindowsPerformanceToolkit`) and inside
+ the Windows ADK, which bundles the same toolkit. Whether the SDK install that
+ Visual Studio performs selects that feature varies by version, so the elevated
+ half **detects first** — `%ProgramFiles(x86)%\Windows Kits\10\Windows
+ Performance Toolkit`, its 64-bit twin, and the ADK location — and only falls
+ back to `winget install Microsoft.WindowsADK` when nothing is there. It then
+ re-asserts that directory on the machine `PATH` (the toolkit's own installer
+ usually does this, and the Start Menu gets *Windows Kits > Windows Performance
+ Toolkit* shortcuts for WPA and WPR). To install just the toolkit instead of the
+ whole ADK, run the standalone SDK setup with
+ `winsdksetup.exe /features OptionId.WindowsPerformanceToolkit /q`. A newer WPA
+ also exists in the Microsoft Store (`winget install --id 9N0W1B2BXGNZ --source
+ msstore`); it is not installed here because the Store source needs an
+ interactive, signed-in session, which the unattended elevated half does not
+ have.
+- **Tracing without a UAC prompt.** `xperf` and `wpr` fail for a standard user in
+ two different ways, because two different things are missing:
+
+ ```text
+ xperf -on base -> NT Kernel Logger: Access is denied. (0x5)
+ wpr -start GeneralProfile -> Failed to enable the policy to profile system performance.
+ ```
+
+ Three separate things are in the way, and all three have to be dealt with:
+
+ 1. Creating or controlling *any* ETW session — even a user-mode one naming a
+ single provider — is checked against the security descriptor ETW keeps per
+ provider GUID under `HKLM\SYSTEM\CurrentControlSet\Control\WMI\Security`,
+ whose **default** grants the session-control rights to SYSTEM,
+ Administrators, the service accounts and `BUILTIN\Performance Log Users`,
+ and to nobody else.
+ 2. Switching on the *kernel* provider needs the `SeSystemProfilePrivilege` user
+ right ("Profile system performance"), held by default only by
+ Administrators and `NT SERVICE\WdiServiceHost` — that is the one `wpr`
+ names.
+ 3. The kernel logger is not covered by that default descriptor.
+ `SystemTraceControlGuid` — the session both `xperf -on` and `wpr` drive —
+ carries an explicit one that does not mention Performance Log Users. With
+ 1 and 2 in place a user-mode session starts and the privilege is held, and
+ `xperf -on base` *still* answers "NT Kernel Logger: Access is denied" while
+ `wpr`'s error changes to a bare `0x80070005`; even reading that descriptor
+ comes back access-denied, which is the tell. So an ACE for the group is
+ added with `EventAccessControl`, `TRACELOG_ACCESS_KERNEL_LOGGER` included.
+
+ The privilege and the ACE both go to the **group**, and the account then goes
+ into the group, so membership alone is the switch and enabling another account
+ afterwards is just `net localgroup "Performance Log Users" <user> /add`.
+ `SeDebugPrivilege` is deliberately *not* granted: CPU sampling and stack walks
+ of your own processes do not need it, and it is equivalent to handing out
+ administrator. Worth being clear about the cost: a member of that group can
+ capture system-wide kernel traces — process, image, file and registry activity
+ across every account on the box, paths and command lines included.
+
+ Two consequences worth knowing. A privilege and a group membership are both
+ read into the access token **at logon**, so the account must sign out and back
+ in for 1 and 2 — any new logon does it, and an `ssh` login into the box is the
+ quick way to check without dropping the desktop. The ACE in 3 is machine state
+ instead, and a logon does nothing for it: ETW reads these descriptors into a
+ cache, so it takes a **reboot** — with the ACE written and readable, `xperf -on
+ base` was still denied from a fresh shell on the running system. Plan on both
+ on a first run. And this only
+ helps a **non-admin** account: UAC hands an administrator a filtered token
+ carrying just five harmless privileges, so an admin's ordinary shell still
+ cannot trace however the policy reads. Verify from the target account,
+ unelevated:
+
+ ```powershell
+ whoami /priv | findstr SeSystemProfilePrivilege
+ xperf -on base ; xperf -stop C:\Temp\trace.etl
+ ```
+
+ Analysis never needed any of this — `wpa.exe` opens an existing `.etl` as a
+ plain user. This is only about collection.
+
+ The rights step runs **first** in the elevated half, and `-EtwRightsOnly` runs
+ it and nothing else. It is seconds of LSA and registry work where a full run is
+ dominated by the three Visual Studio passes, which take minutes even with
+ nothing to do:
+
+ ```powershell
+ Start-Process powershell -Verb RunAs -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass',
+ '-File','<repo>\setup-windows-with-uac.ps1','-TraceUser','DOMAIN\user','-EtwRightsOnly'
+ ```