HomeNewsletterCommunityMVP FeedToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog
Windows Update Windows UpdateETWGet-WindowsUpdateLogWindowsUpdate.logTroubleshootingWindows 11USOwuaueng.dll

WindowsUpdate.log is 276 bytes of pointer text: reading the real ETW traces with Get-WindowsUpdateLog

IA
Imran Awan
23 August 2026

Somebody reports that updates have stopped. You remote in, open C:\Windows\WindowsUpdate.log, and the entire file is four lines long.

Not truncated. Not empty. Four lines, 276 bytes, telling you to run a PowerShell command.

At this point a lot of admins conclude logging is broken, or that something wiped the log. Neither is true. That file has been a signpost rather than a log since Windows 8.1, and the real evidence sits in ninety-nine binary trace files in a subdirectory nobody opens.

This post is about getting at that evidence, and reading it, before you touch a service.

The short version

Microsoft documents that starting in Windows 8.1, the Windows Update client uses Event Tracing for Windows (ETW) instead of writing a text log. The real evidence is a rolling set of .etl files in C:\Windows\Logs\WindowsUpdate, written by a live ETW session called WindowsUpdate_trace_log. Get-WindowsUpdateLog merges and decodes those files into one readable WindowsUpdate.log, by default on your Desktop. It used to need a Microsoft symbol server; from Windows 10 1709 onward it does not, and the SymbolServer parameter is deprecated. Decode first. The reflex fix of stopping wuauserv and deleting SoftwareDistribution destroys the datastore that the decoded log's identifiers point at, and -ForceFlush stops services too, so order matters.

The problem: WindowsUpdate.log is 276 bytes of pointer text

The file still exists. That is what makes the trap effective.

If C:\Windows\WindowsUpdate.log had been deleted outright, everyone would have learned the new method in a week. Instead Microsoft left a stub, so the muscle memory still works, the file still opens, and the result looks like a broken log rather than a redirect.

Here is that file on the Windows 11 device I used. Read-only, nothing changed.

PowerShell
Get-Item C:\Windows\WindowsUpdate.log | Select-Object Length, LastWriteTime # How big is the "log"? Length LastWriteTime ------ ------------- 276 8/23/2026 10:27:01 AM Get-Content C:\Windows\WindowsUpdate.log Windows Update logs are now generated using ETW (Event Tracing for Windows). Please run the Get-WindowsUpdateLog PowerShell command to convert ETW traces into a readable WindowsUpdate.log. For more information, please visit https://go.microsoft.com/fwlink/?LinkId=518345 # 276 bytes. That is the whole file. It is a signpost, not a log.

Note the LastWriteTime: 10:27 that same morning. Something rewrote the stub hours earlier. That timestamp is the best clue on the device, and I will come back to what it means.

The damage is not the wasted five minutes. It is what people do next. Finding no log, the reflex is the standard reset: stop wuauserv and bits, delete C:\Windows\SoftwareDistribution, restart, retry.

Sometimes that clears the symptom. It also guarantees you never learn the cause, which matters on a fleet, because that cause is about to hit two hundred more devices.

Watch out: Microsoft documents that the local update datastore lives at %WINDIR%\SoftwareDistribution\Datastore\Datastore.edb, and that the "Local IDs" you see in Windows Update logs are serial numbers issued by that datastore. Delete SoftwareDistribution and every local identifier in the log you have not decoded yet becomes unresolvable. You have not fixed the device, you have shredded the only copy of the evidence and reset the counters that would have told you whether the problem recurred.

Why it happens: the agent writes ETW, and the agent is not where you think

What ETW actually is

Event Tracing for Windows is a kernel-level tracing facility. A component registers as a provider with a GUID and emits events into a buffer; a session subscribes to providers and drains those buffers to disk as .etl files.

The part that matters for troubleshooting is what the provider writes. To keep tracing cheap enough to leave on permanently, providers do not write your readable sentence. They write a numeric event ID plus raw arguments, and the human-readable format string lives outside the trace, in the binary's metadata or symbols.

That is the whole reason a decode step exists. The .etl file is not encrypted or corrupt, it is shorthand. Opening one in Notepad gives you mojibake because the sentence you want was never in there.

Context: the common belief is that this changed in Windows 10. Microsoft's log reference is more precise, stating that ETW logging began "starting in Windows 8.1 and continuing in Windows 10". Windows 10 is simply when the fleet noticed, because that is when most runbooks broke at once.

Three sessions, not one

Windows Update does not have a single log. Three separate ETW sessions run on an idle, healthy Windows 11 device, covering different stages of the same operation. Decode only the first and you miss entire classes of failure.

SessionWrites toCovers
WindowsUpdate_trace_logC:\Windows\Logs\WindowsUpdateThe Windows Update Agent: scan, applicability, metadata, download, installer handoff.
UpdateSessionOrchestrationC:\ProgramData\USOShared\LogsThe Update Session Orchestrator: the decisions about when to scan, download, install and reboot.
NotificationUxBrokerC:\ProgramData\USOShared\LogsThe toast and banner the user did or did not see.

Microsoft's guidance on which to read is unusually direct: go to the orchestrator logs when "updates are available but download isn't getting triggered", when "updates are downloaded but installation isn't triggered", and when "updates are installed but reboot isn't triggered".

A clean split. Agent log for "the update never arrived". Orchestrator log for "it arrived and then nothing happened".

The binaries behind the agent

Every component tag in the decoded log maps to a real file. Knowing which file, and where it lives, is what lets you check a version or spot a tampered install. These versions come from the device I used, read with Get-Item.

FileLocation and roleVersion on this device
wuaueng.dllSystem32. Described as "Windows Update Agent". The agent core, and the source of the Agent, ProtocolTalker and DownloadManager traces.1509.2607.1012.0
wuapi.dllSystem32. Described as "Windows Update Client API": the COM surface documented in wuapi.h, exposing IUpdateSession and IUpdateSearcher. ComApi traces come from callers crossing this boundary.1509.2607.1012.0
MoUsoCoreWorker.exeNot in System32 - it is at C:\Windows\UUS\amd64. Described as "MoUSO Core Worker Process": the orchestrator worker that calls the agent.1509.2607.1012.0
usosvc.dllSystem32. "Update Session Orchestrator Service" - the service DLL behind UsoSvc.10.0.26100.8737
usoapi.dllSystem32. "Update Session Orchestrator API".10.0.26100.8521
UsoClient.exeSystem32. Command-line entry point into the orchestrator.10.0.26100.8328

Look at the version column, because it holds the most useful thing in this table. The orchestrator files carry 10.0.26100.x, a normal Windows build number. The agent files carry 1509.2607.1012.0, which is not a Windows build number at all. And MoUsoCoreWorker.exe sits under C:\Windows\UUS beside a uusp.json and per-architecture folders, not in System32 with everything else.

The practical consequence: the update agent is serviced on its own track with its own version lineage, independent of the OS build. This device reports OS build 10.0.26200.9168 and an agent at 1509.2607.1012.0. Comparing an agent version against an OS build tells you nothing.

Gotcha: a lot of published troubleshooting scripts test for C:\Windows\System32\usocore.dll. On the Windows 11 device I checked, that file does not exist. What is in System32 is usosvc.dll, usoapi.dll, usodocked.dll and usocoreps.dll (the last one being the "USO Core Worker Proxy Stub"), while the actual worker executable is off in C:\Windows\UUS\amd64. A detection rule built on Test-Path against the wrong name will report a healthy device as broken, forever. Verify the filename on a known-good machine before you ship the rule.

How to verify: prove the trace is running before you decode it

Do not start by decoding. Start by establishing that there is anything worth decoding, because "the log is empty" and "the trace was never running" need different fixes. Follow these in order; each step either clears the device or hands you the root cause.

1. Session running?2. ETLs on disk?3. Fresh or stale?4. Decode

Step 1. Confirm the ETW sessions are alive. One command settles the "logging is broken" question outright.

PowerShell - elevated
logman query -ets | Select-String 'Update' # Lists live ETW trace sessions whose name mentions Update. MpWppUpdateLogging Trace Running WindowsUpdate_trace_log Trace Running UpdateSessionOrchestration Trace Running # HEALTHY: WindowsUpdate_trace_log and UpdateSessionOrchestration both Running. # If either is missing, no amount of decoding will produce data for that stage. # MpWppUpdateLogging is Defender, not Windows Update. Do not chase it.

Step 2. Read the session configuration. Almost nobody does this, and it answers the two questions that decide whether your evidence still exists: where is it, and how long does it survive?

PowerShell - elevated
logman query 'WindowsUpdate_trace_log' -ets Name: WindowsUpdate_trace_log Status: Running Root Path: C:\WINDOWS\Logs\WindowsUpdate Segment Max Size: 512 MB Output Location: C:\WINDOWS\Logs\WindowsUpdate\WindowsUpdate.20260823.102701.286.1.etl Circular: Off Buffer Size: 4 Buffers Written: 92 Buffers Lost: 0 Clock Type: Performance Provider: Provider Guid: {0B7A6F19-47C4-454E-8C5C-E868D637E4D8} Level: 4 KeywordsAny: 0x1ffffff # Root Path = where the .etl files land. Matches Microsoft's documented location. # Output Location = the segment being written RIGHT NOW. # Buffers Lost: 0 = no events dropped. Non-zero means gaps in your evidence. # Segment Max Size 512 MB = the cap. Old traces roll off. Evidence expires.

Three readings matter here.

Buffers Lost is your data-integrity check. Zero means the trace kept up. Non-zero means events were dropped under load, so a gap in the decoded log at the interesting moment may be an artefact rather than a clue.

The Output Location filename solves the timestamp puzzle from earlier. It reads WindowsUpdate.20260823.102701.286.1.etl, and the stub file's LastWriteTime was 10:27:01 that same day. Same moment: the session rolled to a new segment and rewrote the stub, exactly what you expect after a reboot or service restart. A stub timestamp far in the past is a real red flag; one matching the live segment is a healthy device.

Segment Max Size is the one with a deadline attached. Traces roll. If a user reports a failure from three weeks ago, the trace covering it may be gone, and no fix recovers it.

Tip: when a user reports an update failure, collect the .etl files first, before you try anything. A plain Copy-Item C:\Windows\Logs\WindowsUpdate\*.etl to a share takes seconds, needs no decoding, and freezes the evidence while you still have it. Decode later at your desk, on any machine running 1709 or newer. On my device the whole directory was 99 files and about 42 MB, which is nothing next to being unable to answer the question at all.

Step 3. Inventory the ETLs and check freshness.

PowerShell
$e = Get-ChildItem C:\Windows\Logs\WindowsUpdate -Filter *.etl "count = " + $e.Count + " totalMB = " + [math]::Round(($e | Measure-Object Length -Sum).Sum/1MB,1) $e | Sort-Object LastWriteTime | Select-Object -Last 3 Name, Length count = 99 totalMB = 42.5 Name Length ---- ------ WindowsUpdate.20260822.153224.796.7.etl 532480 WindowsUpdate.20260822.153224.796.8.etl 241664 WindowsUpdate.20260823.102701.286.1.etl 372736 # Naming: WindowsUpdate.<yyyymmdd>.<hhmmss>.<ms>.<segment>.etl # Each session start gets a new timestamp; segments increment within it. # HEALTHY: newest file dated today, and still growing (below 512 KB segment fill). # BROKEN: newest .etl is weeks old = the agent has not run, which is the real fault.

That last distinction is the payoff for doing steps 1 to 3 at all. An old newest-ETL is not a logging problem, it is the symptom: the agent is not being invoked, so look at the orchestrator next.

Where the agent keeps its state

The decoded log constantly refers to service IDs, SLS decisions and reporting state. Those live under one parent key.

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate
ValueMeaningWhat to look for
ServicesUpdate services registered with the agent (Windows Update, Microsoft Update, WSUS, DCat Flighting).Cross-reference the ServiceId GUIDs on ProtocolTalker lines. An unexpected service ID here explains an unexpected scan source.
SLSService Location Service cache: the endpoints the agent was told to talk to.Pair with SLS-tagged log lines. A stale cache alongside SLS errors points at network or proxy, not the agent.
OrchestratorScan, download and install scheduling state owned by USO.Populated but no recent activity in the decoded log means the orchestrator is not calling the agent.
ReportingState for reporting results back to the service.Correlate with Reporter lines when a device installs updates but never reports compliance.
Auto UpdateAgent-side automatic update state, including the RebootRequired marker.RebootRequired here is a genuine pending-reboot signal. Absent on the clean device I checked, as expected.
ClientCacheCached client-side metadata.Relevant when Metadata lines show repeated refetches of the same data.
TraceDoes not exist.Older blog posts tell you to create trace flags here. There is no Trace subkey and creating one does nothing. Tracing is configured through the ETW session.

The fix: Get-WindowsUpdateLog, run properly

Now decode. Microsoft's description is worth reading literally: the cmdlet "merges and converts Windows Update .etl files into a single readable WindowsUpdate.log file".

Two verbs. It merges the directory of segments into one chronological stream, and it converts shorthand events into sentences. The output is a new file, not a view onto the old ones.

ParameterWhat it doesWhen to use it
-ETLPathSource. A directory, a single .etl, or a comma-separated list. Defaults to the local trace directory.Point it at ETLs copied off another device. This is what makes offline triage possible.
-LogPathDestination file. Defaults to WindowsUpdate.log on the current user's Desktop.Always set it. A case folder beats littering Desktops.
-IncludeAllLogsDecodes Windows Update, the orchestrator and the update UX into WindowsUpdate.log, USO.log and UX.log. Mutually exclusive with every other parameter.Any "downloaded but never installed" or "never prompted the user" case.
-ForceFlushForces the agent to flush pending traces to .etl. Microsoft documents that this stops the Update Orchestrator and Windows Update services. Needs elevation.Only when you need the last seconds before a failure. Read the warning below first.
-ProcessingTypeXML (default) or CSV for intermediate temp files, which land in $env:TEMP\WindowsUpdateLog.Rarely. Switch to CSV to sidestep XML schema warnings.
Watch out: -ForceFlush is not a harmless "get me the freshest data" switch. Microsoft states plainly that it stops the Update Orchestrator and Windows Update services to do its job. If you are troubleshooting a live in-progress operation, running it will interrupt that operation and change the very state you are measuring. Run the cmdlet without -ForceFlush first. You almost always have what you need, because the session flushes on its own.

The symbol server history, and why it stopped mattering

If you inherited a runbook saying this decode needs internet access to Microsoft's symbol server, that runbook is at least eight years old, but it was not wrong when written.

Microsoft documents the boundary precisely. For Windows 10 versions before 1709 (build 16299), the cmdlet required access to a Microsoft symbol server and decoding had to be done from a pre-1709 build. From 1709 onward no symbol server is needed, and logs must be decoded on 1709 or higher. The SymbolServer parameter survives in the older documentation, explicitly marked deprecated for 1709 and above.

That is why the old runbook produced garbage logs full of unresolved placeholders on locked-down networks: the decode was silently failing to fetch format strings. On anything modern that data ships with the OS and the failure mode is gone.

Gotcha: the decoded log is a static snapshot. Microsoft's note is explicit: the file "is created as a static log file. It does not update as the old WindowsUpdate.log unless you run Get-WindowsUpdateLog again." Every admin who has ever tailed this file has been fooled once. Reproduce the failure, then decode, in that order. Decoding first and watching for new lines will show you nothing forever.

Reading the result: the format and the tags

Microsoft documents the decoded log as four identities: timestamp, process and thread ID, component name, and update identifiers. In practice you read the component column and ignore most of the file. Here is the documented list, condensed to the tags that carry weight in a real investigation.

TagWhat it isRead it when
AgentThe Windows Update agent itself: scan start and end, applicability results.Always. "Found N updates" lands here.
ProtocolTalkerClient-to-server sync.Scan fails, times out, or hits the wrong endpoint.
DownloadManagerCreates and monitors payload downloads.Download stalls at 0% or errors.
ComApiThe Windows Update API surface, i.e. wuapi.dll callers.Identifying who triggered a scan; the caller is on the line.
Handler, SetupInstaller handlers, CBS among them.Download succeeds, install fails. Your handoff to CBS.log.
EEHandlerEvaluating update applicability rules.An update you expect is never offered.
DataStoreCaching update data locally, i.e. Datastore.edb.Corruption suspicions, before you delete anything.
IdleTimerTracking active calls and stopping the service.Operations that abandon partway.
Context: Microsoft's published component list is not exhaustive. Decoding a real device's traces produced high-volume tags that appear nowhere in the documentation, including WebServices, Deployment, Metadata, Shared, Reporter, Driver and SLS. Do not assume an unfamiliar tag means a corrupt decode. Also note that Microsoft's structure documentation describes process and thread IDs as four hex digits each, which reflects the older format; the modern decoded output prints them as plain decimal columns.

Proof it worked: one scan, three independent records

The test of a decode is not that a file appeared. It is whether you can take one event and find it in three places written by three different mechanisms. If they agree, your evidence is sound.

I ran the cmdlet against the real trace directory without -ForceFlush, so no service was touched.

PowerShell - real run, services untouched
Get-WindowsUpdateLog -LogPath D:\Cases\4417\WindowsUpdate.log Getting the list of all ETL files... Please wait for all of conversions to complete... ================ Results from WULog_0 ================ Input ---------------- File(s): C:\WINDOWS\logs\WindowsUpdate\WindowsUpdate.20260810.085032.624.2.etl C:\WINDOWS\logs\WindowsUpdate\WindowsUpdate.20260810.085032.624.3.etl ... 8 more ... 100.00% Output ---------------- DumpFile: C:\Users\<user>\AppData\Local\Temp\WindowsUpdateLog\wuetl.XML.tmp.GUID.00000 Warning: Some events do not match the schema. Please rerun the command with -lr to get less restricted XML dump The command completed successfully. # It batches the 99 ETLs into groups (WULog_0, WULog_1, ...) and decodes each. # The schema warning is NORMAL and appeared on every batch on a healthy device. # It is not corruption. Do not chase it. Get-Item D:\Cases\4417\WindowsUpdate.log | Select-Object Length (Get-Content D:\Cases\4417\WindowsUpdate.log | Measure-Object).Count Length : 18614570 116504 # 17.75 MB, 116,504 lines, from a device with NO reported update problem. # This is why you filter by component tag instead of scrolling.

The schema warning appeared on every batch, on a device with no update fault, and the cmdlet reported success each time. Treat it as noise unless the output file is missing.

Now the correlation. Here are the last lines of the decoded log, landing at 10:43:24 on 2026-08-23.

Decoded WindowsUpdate.log - real lines, tail of file
2026/08/23 10:43:24.7905596 24108 38280 ComApi * END * Search ClientId = MoUpdateOrchestrator, Updates found = 0, ServiceId = 8B24B027-1DEE-BABB-9A95-3517DFB9C552 2026/08/23 10:43:24.7910339 24108 27496 ComApi * END * All federated searches have completed. Jobs = 2, Succeeded = 2, ClientId = MoUpdateOrchestrator # Column 1-2 = timestamp. Column 3 = PID (24108). Column 4 = TID. # Column 5 = component tag: ComApi, so this crossed wuapi.dll. # ClientId = MoUpdateOrchestrator names the CALLER: the orchestrator, # i.e. MoUsoCoreWorker.exe, asked the agent to scan. Not a user, not Intune. # "Updates found = 0" is the scan result. Remember that number.

Earlier in the same file, an Agent-tagged line shows the same kind of operation from the agent's side rather than the API's, carrying the applicability arithmetic:

2026/08/10 13:16:36 15780 25264 Agent Found 12 updates and 74 categories in search;
  evaluated appl. rules of 702 out of 894 deployed entities

Twelve updates found, 702 applicability rules evaluated out of 894 deployed entities. When an update you expect is never offered, that ratio and the nearby EEHandler lines are where the answer is.

Now the third record. The same scans are reported independently to the event log, by the event channel below.

Microsoft-Windows-WindowsUpdateClient/Operational

These are the real counts from that channel on the same device, over the retained window.

Event IDMessageWhat it tells you
26Windows Update successfully found 0 updates.A scan completed. The number is the answer to "did the device see the patch?". Seen 1,815 times here. Correlate the timestamp against the Agent or ComApi "Updates found" line to identify which caller ran it.
41An update was downloaded.Payload transfer completed. Seen 335 times. Pairs with DownloadManager lines in the decoded log, which carry the DO job ID and update GUID that this event omits.
25Windows Update failed to check for updates with error 0x80240438.Scan failure with the error code attached. Seen 24 times. Take the timestamp to the decoded log and read the ProtocolTalker and SLS lines around it.
31Windows Update failed to download an update.Download failure. Seen twice. The event does not say which update or why; the DownloadManager lines at that timestamp do.

That table is the argument for this whole exercise. The event log tells you that something happened, with a timestamp. The decoded log tells you which update, caller, endpoint and error. Neither suffices alone, and the event log is the one that survives a SoftwareDistribution reset.

So the three records for the 10:43 scan agree: the live ETL segment WindowsUpdate.20260823.102701.286.1.etl was receiving events, the decoded log's final entry reads Updates found = 0 at 10:43:24, and Event 26 reads "successfully found 0 updates". Three mechanisms, one story. That is a trustworthy decode.

One last real detail, because it settles the version question from earlier. The agent stamps its own version into the device attributes it sends on every scan:

ProtocolTalker DeviceAttributes[URI]: ... &AppVer=1508.2606.17012.0
  &WuClientVer=1508.2606.17012.0&OSVersion=10.0.26200.8875
  &OSArchitecture=AMD64&InstallationType=Client&TenantId=REDACTED

On 10 August this device reported WuClientVer=1508.2606.17012.0. By 23 August the on-disk agent was 1509.2607.1012.0 - a full generation, while the OS build barely moved. If a scan fails on some devices and not others, WuClientVer beats the OS build as a comparison across the fleet, and it is only visible here.

References

Everything measured here came from one Windows 11 Enterprise device, build 26200.9168, read-only except the decode itself.

Was this post helpful?
React below — no account needed
Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Windows Update
wuauclt /detectnow Does Nothing: Diagnosing Patching Through the…
wuauclt /detectnow returns instantly and silently because it stopped working years ago.…
Windows Update
0x80070002 and 0x8007000D: the same two Win32 codes mean five…
Neither code is a Windows Update error code, which is why the advice for them contradicts…
Windows Update
The Windows patching triage decision tree: which log, which key,…
Route each patching symptom to the one evidence source that answers it. Then learn the…