An auditor asks something trivial. Is the August cumulative update on this device, and when did it install?
You pick one of four ways to answer and close the ticket. Then somebody answers from a different source and gets a different date. Neither of you is wrong, and neither can explain the gap.
Four sources answer "what happened to this device" and none is a superset of the others. Get-HotFix reads Win32_QuickFixEngineering, documented as returning "only the updates supplied by Component Based Servicing (CBS)" - here, 4 rows. The WUA COM history (IUpdateSearcher::QueryHistory) returned 153 rows for the same machine, including 41 failed attempts at an update never installed - but zero rows for two of the four KBs Get-HotFix reports. The component store held 415 packages (199 Superseded / 121 Installed / 95 Staged), of which exactly one name contains a KB number. Settings is a UI over the WUA record, not a fifth source. Learn which question each answers, because the reflex fix - deleting SoftwareDistribution - destroys the only source that records failures.
The problem: four sources, four answers, one device
Everything below was measured read-only on one Windows 11 Enterprise machine, build 26200.9168, DisplayVersion 25H2, on 23 August 2026.
Three sources, three shapes of answer. Get-HotFix gave a date with no time. The WUA history gave a timestamp to the second, on a different day. The component store did not recognise the KB at all. None of that is an error - each is a correct answer to a question that is not quite the one that was asked.
The gap between four rows and 153 is the difference between "which CBS packages are installed" and "what did the agent try to do". Treat them as interchangeable and you are wrong both ways.
CBS.log and the ETW traces under C:\Windows\Logs\WindowsUpdate\. Those are transaction logs, not inventories - they tell you how something happened, and they rotate. This article is about the four sources people paste into tickets as if they were equivalent statements of fact.Why it happens: each source records a different event
Source 1: Get-HotFix only ever sees CBS
The Win32_QuickFixEngineering reference states it in one sentence: "This class returns only the updates supplied by Component Based Servicing (CBS). These updates are not listed in the registry. Updates supplied by Microsoft Windows Installer (MSI) or the Windows update site (https://update.microsoft.com) are not returned by Win32_QuickFixEngineering."
The Get-HotFix help repeats that paragraph verbatim in its Notes - stated twice, in the two places an admin looks, and still the most commonly ignored fact in Windows patch reporting.
What falls outside CBS on a normal corporate device? On mine the WUA history recorded all of these as installed, and not one appears in Get-HotFix: the .NET 8 runtime update KB5122104, PowerShell 7.6.5, the Malicious Software Removal Tool KB890830, Defender security intelligence KB2267602, and five vendor driver updates.
There is a stranger detail in the same class definition. The MOF maps HotFixID to a MappingStrings qualifier of Win32Registry|SOFTWARE\Microsoft\Windows NT\CurrentVersion\Hotfix - while the prose above says these updates "are not listed in the registry". Both are true, and the resolution is measurable.
| Value or subkey | Meaning | What to look for |
|---|---|---|
Hotfix (subkey) | The legacy QFE location the Win32_QuickFixEngineering MOF still points at | Test-Path returned False. The key does not exist - the CBS rows are synthesised by the provider, which is why the doc says they are not in the registry |
CurrentBuild | OS build, e.g. 26200 | The only reliable release discriminator. Always pair it with UBR |
UBR | Update Build Revision, e.g. 9168 | KB5121003 yields UBR 9168 on both 25H2 (26200) and 24H2 (26100). Testing UBR -ge 9168 without pinning CurrentBuild passes a 24H2 device against a 25H2 baseline |
ProductName | Edition string | Reads "Windows 10 Enterprise" on this Windows 11 device. Scripts keying on it fail silently |
Source 2: the WUA history is a per-attempt event log in a database you have been told to delete
The COM entry point is IUpdateSearcher::QueryHistory(startIndex, count, retval), implemented in wuapi.dll. It returns an IUpdateHistoryEntryCollection documented as containing "matching event records on the computer in descending chronological order".
Read the companion method name carefully. GetTotalHistoryCount returns "the number of update events on the computer" - not updates. That one word is the whole behaviour: an update that retries forty-one times produces forty-one rows.
Not hypothetical. KB5074109 accounts for 41 of my 153 rows, every one orcFailed with 0x80240034, and there is no success row for it anywhere. It was never installed - a later cumulative update superseded it and the retries stopped.
The store behind all of this is C:\Windows\SoftwareDistribution\DataStore\DataStore.edb, 54.75 MB here, with a documented error family of its own: the WU_E_DS_* codes, 0x80248000 to 0x80248FFF. It is also the first thing every troubleshooting script deletes.
Source 3: the component store knows components, not KBs
Get-WindowsPackage -Online returned 415 rows, and the state split is what no other source exposes.
Only one of 415 names carries a KB number, and it is the enablement package. Everything else is named by component and version: the August servicing stack update is Package_for_ServicingStack_9156~31bf3856ad364e35~amd64~~26100.9156.1.0. No KB, even though Get-HotFix lists it as KB5123304.
So the store cannot answer "is KB X installed" by name. What it can answer, and nothing else can, is which component versions are present and in which of three states. The DISM API documents these as DismPackageFeatureState: DismStateStaged (2), DismStateInstalled (4), DismStateSuperseded (6), plus DismStateNotPresent (0), DismStateUninstallPending (1), DismStateRemoved (3), DismStateInstallPending (5) and DismStatePartiallyInstalled (7).
Those 95 Staged packages are why this source exists: the payload is on disk and CBS has not promoted it. Nothing else distinguishes "downloaded" from "running".
Get-HotFix reports KB5054156 with Description = Update, installed 4 February 2026. Microsoft's KB describes it as a "small, quick-to-install 'master switch' that activates the Windows 11, version 25H2 features", because 24H2 and 25H2 "share a common core operating system with an identical set of system files" and the 25H2 features ship dormant inside the 24H2 monthly update. That one-word Description hides a whole release move. The store even names it Package_for_KB5054156~31bf3856ad364e35~amd64~~26100.6717.1.4 - a 26100 version number on a 26200 device, the shared core showing through. Any inventory that buckets by Description files an OS release change next to a font update.Source 4: Settings is a view, not a record
Admins cite the Settings page as an independent authority. Microsoft's guidance describes the plumbing: "The Settings UI communicates with the Update Orchestrator service that in turn communicates with to Windows Update service."
So it is a client of the same agent, reading the same datastore, presented in categories. The documented UI error family is the giveaway: 0x80243001, 0x80243002 and 0x80243003 - the WU_E_INSTALLATION_RESULTS_* codes - all describe results that "couldn't be read from the registry". The UI has its own read path and its own ways to fail.
It inherits every limitation of source 2 and adds one: you cannot query, filter, export or join it. Use it to confirm what a user saw, never what a device did.
The binaries doing the work
| File | Verified location | Role |
|---|---|---|
wuapi.dll | C:\Windows\System32\, version 1509.2607.1012.0 | "Windows Update Client API" - the COM surface implementing QueryHistory. Microsoft's reset procedure re-registers it by name |
wuaueng.dll | C:\Windows\System32\, version 1509.2607.1012.0 | "Windows Update Agent", the ServiceDll for wuauserv. Serviced separately from the OS, which is 10.0.26200.9168 |
CIMWin32.dll | C:\Windows\System32\wbem\ | "WMI Win32 Provider" - implements Win32_QuickFixEngineering. The CBS-only limitation lives here |
TiWorker.exe | versioned WinSxS servicing-stack directory, not System32 or C:\Windows\servicing | "Windows Modules Installer Worker" - does the staging and promotion behind the Setup events below |
How to verify: read all four before you conclude anything
Here is the order I use. Every destructive option comes after every read-only one.
- Establish the release facts.
CurrentBuild,UBR,DisplayVersion- a KB maps to different builds on different releases. - Run
Get-HotFixand treat it as a floor, not a total. MSI, Store, driver and Defender content is missing by design. - Pull the full WUA history and count events, not updates. Group by
Titlefirst, or retries distort every number. - Decode
ResultCodeandOperationwith the documented enums, not by eye. - Check
ClientApplicationIDbefore blaming Windows Update. Here, 43 of 153 events came from setup and Store installers. - Find the datastore horizon. Compare
DataStore.edb'sCreationTimewith the oldest history row. Anything earlier is invisible to sources 2 and 4, permanently. - Take the component-store census. Your only view of Staged and Superseded.
- Only now read the Setup log for the KB in dispute. That turns four disagreeing numbers into one chronology.
Two closed enums decode every row.
| OperationResultCode | Value | Documented meaning |
|---|---|---|
orcNotStarted | 0 | "The operation is not started." |
orcInProgress | 1 | "The operation is in progress." |
orcSucceeded | 2 | "The operation was completed successfully." 99 rows here |
orcSucceededWithErrors | 3 | "The operation is complete, but one or more errors occurred during the operation. The results might be incomplete." |
orcFailed | 4 | "The operation failed to complete." 52 rows here |
orcAborted | 5 | "The operation is canceled." 2 rows here, both 0x8024000B |
UpdateOperation has exactly two members: uoInstallation (1) and uoUninstallation (2). There is no third. All 153 rows here were uoInstallation, which answers a question people ask this API by mistake - the history shows an uninstall only if WUA performed it. A wusa /uninstall or a boot-time CBS rollback leaves no uoUninstallation row at all.
A third enum governs attribution, and trips people up constantly.
| ServerSelection | Value | Documented meaning |
|---|---|---|
ssDefault | 0 | The default server - the same as ssManagedServer if the computer has one |
ssManagedServer | 1 | "Indicates the managed server, in an environment that uses Windows Server Update Services or a similar corporate update server" |
ssWindowsUpdate | 2 | "Indicates the Windows Update service." |
ssOthers | 3 | "Indicates some update service other than those listed previously. If the ServerSelection property ... is set to ssOthers, then the ServiceID property of the object contains the ID of the service." |
Every history row here reported ServerSelection = 3. Read casually, ssOthers sounds alarming on a managed device. It is not. The documentation tells you what to do next: read ServiceID. The KB5121003 row carried 8b24b027-1dee-babb-9a95-3517dfb9c552.
| ServiceID | Name on this device | Notes |
|---|---|---|
7971f918-a847-4430-9279-4a52d1efe18d | Microsoft Update | IsDefaultAUService = True |
8b24b027-1dee-babb-9a95-3517dfb9c552 | DCat Flighting Prod | Microsoft: "feature updates are always delivered through the DCAT service". This carried the LCU row |
855e8a7c-ecb4-4ca3-b045-1dfa50104289 | Windows Store (Prod) | Microsoft's table calls this "Windows Store (DCat Prod)" - the on-device name differs |
rd /s /q %systemroot%\SoftwareDistribution, and Microsoft prefixes it with the words "If all else fails". The manual procedure is more explicit still: renaming DataStore to DataStore.bak sits in step 4, and the doc says step 4 "should only be performed at this point in the troubleshooting if you can't resolve your Windows Update issues after following all steps but step 4." Both destroy DataStore.edb - and with it every failed attempt, every HResult, every ClientApplicationID, the whole basis for finding out why the update failed. My 52 failure rows, including the 41 that identified a permanently stuck KB, would have become zero. You would be left with a clean history, a still-broken device, and nothing to read.The Setup log survives that reset, making it the one durable per-KB chronology on the machine. Microsoft publishes no event-ID catalog for the Microsoft-Windows-Servicing provider, so this table comes from the on-disk manifest and IDs observed live.
| Event ID | Message observed | What it tells you |
|---|---|---|
| 1 | "Initiating changes for package KB5121003. Current state is Absent. Target state is Staged. Client id: UpdateAgentLCU." | A transition is starting. The state words name the ends; Client id names who asked - UpdateAgentLCU, so Windows Update drove it, not DISM or an admin |
| 2 | "Package KB5121003 was successfully changed to the Staged state." / "... to the Installed state." | The transition completed. Read the state word: Staged is not Installed. Only this source dates the two separately |
| 4 | "A reboot is necessary before package KB5121003 can be changed to the Installed state." | CBS has parked the package. Until a matching Event 2 for the Installed state appears, the update is on disk and not in effect - however cheerful the WUA history looks |
That is the reconciliation. CBS moved KB5121003 from Absent to Staged on the 19th, began the promotion to Installed, hit the reboot boundary at 18:37:47, and finished at 09:14:13 the next morning. The WUA history recorded orcSucceeded ten seconds into that gap. Get-HotFix reports InstalledOn = 8/20/2026, agreeing with CBS.
So the "wrong" date was never wrong. The WUA history dated the agent's work; Get-HotFix dated the package reaching its final state; those two events were 14 hours 36 minutes apart.
The fix: match the source to the question
No script makes these four agree. The fix is to stop asking one source a question it cannot answer.
| The question you were actually asked | Authoritative source | Why the others cannot answer it |
|---|---|---|
| "Is CBS update KB X installed and in effect right now?" | Get-HotFix | Lists only what CBS finished installing. The WUA history says succeeded while CBS is still Staged; the store cannot resolve the KB by name |
| "Did this device ever try, and fail, to install KB X?" | WUA QueryHistory | The only source recording failures. A failed install leaves nothing in Get-HotFix or the store, and no trace after a SoftwareDistribution reset |
| "Is a payload staged and waiting for a reboot?" | Get-WindowsPackage + Setup Event 4 | Nothing else exposes the Staged state - 95 of my 415 packages |
| "When exactly did the state change, and who asked for it?" | Setup log, Microsoft-Windows-Servicing | Only source with per-transition timestamps and a Client id. Survives a reset |
| "Was a non-CBS thing installed - .NET runtime, Store app, driver, Defender platform?" | WUA QueryHistory | Get-HotFix excludes all of them by documented design |
| "What release is this device on?" | CurrentBuild + DisplayVersion | The enablement package that moved the release shows as a plain "Update" |
| "Which superseded versions are still on disk?" | Get-WindowsPackage | Only source with the Superseded state - 199 of 415 |
Why a rolled-back update reads as succeeded-then-absent
An orcSucceeded row records that the install operation completed. The enum's own preamble says so: OperationResultCode "Defines the possible results of a download, install, uninstall, or verification operation on an update". The operation, not the end state.
For a CBS update the operation finishes when the package is staged and the promotion queued. The rest happens at reboot, outside that operation, and Microsoft documents that phase separately in the update-handler family: 0x80242014 WU_E_UH_POSTREBOOTSTILLPENDING ("The post-reboot operation for the update is still in progress"), 0x80242015 WU_E_UH_POSTREBOOTRESULTUNKNOWN and 0x80242016 WU_E_UH_POSTREBOOTUNEXPECTEDSTATE. There is even a documented success code that says the job is not done: 0x00240005 WU_S_REBOOT_REQUIRED, "The system must be restarted to complete installation of the update."
So if the boot-time promotion fails and CBS reverses it, you get my timeline with a different ending: a permanent orcSucceeded row dated the 19th, no Get-HotFix entry, the package back to Absent in the store, and a Setup log showing the transition attempted and undone. Succeeded, then absent. Both records correct.
Critically, IUpdateHistoryEntry exposes no reboot-required property. Its members are ClientApplicationID, Date, Description, HResult, Operation, ResultCode, ServerSelection, ServiceID, SupportUrl, Title, UninstallationNotes, UninstallationSteps, UnmappedResultCode and UpdateIdentity, with Categories added by IUpdateHistoryEntry2. Nothing there separates a final success from a provisional one. You have to go to the Setup log.
UpdateIdentity.UpdateID plus RevisionNumber, which is what the API actually keys on. KB5121003 came back as 800d68a0-03d1-47a4-92f3-1feb02f141aa revision 1. Carry the KB alongside as a label for humans, not as the primary key.And do not treat orcFailed as evidence of a broken device. Microsoft's guidance on transient load-shedding states that callers "would get orcFailed or orcSucceededWithErrors" and that "Retrying the operation later is expected to succeed". A single failed row means nothing. Forty-one identical failed rows with no success row, as with KB5074109, means something specific - and you see it only because the history keeps every attempt.
Proof it worked: the reconciliation on a real device
You understand these four sources when you can predict what each will say before you run it. Here is the final pass.
First, the timezone. QueryHistory returned Kind = Unspecified - the API declines to say which clock it used, and the get_Date documentation says only "Gets the date and the time an update was applied". Measured against the Setup log for the same package it is one hour behind local time, on a device in GMT Standard Time during summer time. That is UTC. If you have ever seen a report where the WUA date is an hour or a day off the event log, this is why.
Second, the horizon. DataStore.edb was created on 17 February 2026 at 12:16:02; the oldest surviving history event is 18 February at 11:22:24. The enablement package that took this device to 25H2 installed on 4 February, two weeks before that file existed. Get-HotFix still reports it, because CBS state is not kept in the datastore. The WUA history reports nothing, and never will.
Third, the bounds. The documented remark on QueryHistory is that it "returns WU_E_INVALIDINDEX if the startIndex parameter is less than 0 (zero) or if the Count parameter is less than or equal to 0 (zero)". Both cases raised 0x80240007 exactly as written, and asking for 100,000 rows when 153 exist returned 153 with no error - so the safe idiom really is QueryHistory(0, GetTotalHistoryCount()).
Nothing was fixed here, and nothing needed to be. Four numbers that looked contradictory - 4, 153, 415, and a one-day date gap - now have a single explanation, and every one can be defended to an auditor. That is what a diagnosis is.
References
- Win32_QuickFixEngineering class
- Get-HotFix
- IUpdateSearcher::QueryHistory
- IUpdateSearcher::GetTotalHistoryCount
- IUpdateHistoryEntry and IUpdateHistoryEntry2
- OperationResultCode enumeration
- UpdateOperation enumeration
- ServerSelection enumeration
- Windows Update error code list by component - the
WU_E_UH_POSTREBOOT*family - Additional resources for Windows Update - the reset steps and their ordering
- Windows Update issues troubleshooting - Settings/USO plumbing, DCAT, load shedding
- DismPackageFeatureState enumeration
- Get-WindowsPackage
- KB5054156: Feature update to Windows 11, version 25H2 by using an enablement package