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 http://go.microsoft.com/fwlink/?LinkId=518345The link specified above describes the reasoning for modifying this process and the general guidelines for generating and viewing the WindowsUpdate.log file. While I'm in favor of better performance and using less disk space, this new process takes some getting used to. To quote the ever-wise REO Speedwagon, "you got to roll with the changes". And roll we will. The reason that I am creating this particular blog post is that I recently had to analyze the WindowsUpdate.log files from multiple machines, which was a challenge when you consider the amount of work that needs to be done to get the correct Symbols in place and the burden of running the command locally on each machine. I didn't do that too many times before the PowerShell light bulb lit up in my head to automate the process of gathering the logs from remote machines. In my case, it was much easier to generate them from the remote machine and copy the files locally where I have everything installed that I need to work with the WindowsUpdate.log files.
WDK Download site: https://developer.microsoft.com/en-us/windows/hardware/windows-driver-kit
SDK Download Site: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk
In my experience, TraceFMT.exe has worked more reliably to convert the files than the native Get-WindowsUpdateLog cmdlet.
Symbols Download Site: https://developer.microsoft.com/en-us/windows/hardware/download-symbols
############################################################################################### # # The sample scripts are not supported under any Microsoft standard support # program or service. The sample scripts are provided AS IS without warranty # of any kind. Microsoft further disclaims all implied warranties including, without # limitation, any implied warranties of merchantability or of fitness for a particular # purpose. The entire risk arising out of the use or performance of the sample scripts # and documentation remains with you. In no event shall Microsoft, its authors, or # anyone else involved in the creation, production, or delivery of the scripts be liable # for any damages whatsoever (including, without limitation, damages for loss of business # profits, business interruption, loss of business information, or other pecuniary loss) # arising out of the use of or inability to use the sample scripts or documentation, # even if Microsoft has been advised of the possibility of such damages # ############################################################################################### # # THIS SCRIPT WILL ALLOW A CENTRALIZED ADMIN WORKSTATION TO REMOTELY GENERATE # WINDOWSUPDATE.LOG ETL FILES AND WILL COPY THEM TO A LOCAL LOCATION FOR ANALYSIS. # IT PLACES THE ETL FILES IN SUBDIRECTORIES ORGANIZED BY DATE AND UTILIZES TRACEFMT.EXE # TO GENERATE THE FINAL WINDOWSUPDATE.LOG FILE. # # PREREQUISITES: # ============================================================================================ # 1. TRACEFMT.EXE (PART OF THE WINDOWS WDK AND SDK) # WDK Download site: https://developer.microsoft.com/en-us/windows/hardware/windows-driver-kit # DK Download Site: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk # 2. WINDOWS SYMBOLS # SYMBOLS (FOR EACH SPECIFIC OS BEING ANALYZED) # SYMBOLS DOWNLOAD: https://developer.microsoft.com/en-us/windows/hardware/download-symbols # # 3. CREATE A FOLDER TO BE USED AS A BASE FOR STORAGE OF ALL FILES PULLED FROM REMOTE MACHINES # # # SYNTAX/USAGE: # ============================================================================================ # WindowsUpdateLogs.ps1 -Computer "SomePC1" -WorkDir "C:\Work" <-SymbolPath "X:\SymbolPathHere"> # <-TraceFMTPath X:\TraceFMTEXEPathHere> Param ( [Parameter(Mandatory=$true)][string]$Computer, [Parameter(Mandatory=$true)][string]$WorkDir, [string]$SymbolPath = "C:\Symbols", [string]$TraceFMTPath = "C:\Program Files (x86)\Windows Kits\10\bin\x86" ) # VERIFY THAT THE $WorkDir PATH SPECIFIED EXISTS If (!(Test-Path $WorkDir)) { Write-Output "$WorkDir path not found, exiting script" Exit 99 } # VERIFY THAT THE PATH SPECIFIED CONTAINS THE TRACEFMT.EXE TOOL SINCE IT IS REQUIRED If (!(Test-Path $TraceFMTPath\TraceFmt.exe)) { Write-Output "TraceFmt.exe not found at $TraceFMTPath, exiting script" Write-Output "TraceFmt.exe is part of the Windows Driver Kit and Software Development Kit" Write-Output "WDK Download: https://developer.microsoft.com/en-us/windows/hardware/windows-driver-kit" Write-Output "SDK Download: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk" Exit 99 } # VERIFY LOCATION OF SYMBOLS DIRECTORY (REQUIRED) If (!(Test-Path $SymbolPath)) { Write-Output "Symbols not found at $SymbolPath, exiting script" Write-Output "If you need to download symbols, they are available at:" Write-Output "https://developer.microsoft.com/en-us/windows/hardware/download-symbols" Write-Output "=========================================================================================" Write-Output "NOTE: Symbols must match the OS version that you are pulling the Windows Update logs from" Write-Output "=========================================================================================" Exit 99 } # SET UP SESSION ON REMOTE COMPUTER $Sess = New-PSSession -ComputerName $Computer Enter-pssession $Sess # RUN THE COMMAND TO GENERATE THE WINDOWS UPDATE LOGS ON THE REMOTE COMPUTER Invoke-Command -Session $Sess -ScriptBlock {Get-WindowsUpdateLog} # EXIT PSSESSION Exit-PSSession # SET UP A TARGET DIR TO STORE FILES $strTargetDir = "$WorkDir\$Computer" [array]$arrWULogs = Get-ChildItem "\\$Computer\c$\WINDOWS\logs\WindowsUpdate\WindowsUpdate*etl" ForEach ($log in $arrWULogs) { $FileDate = $log.LastWriteTime.date $strFileDate = $FileDate.ToString("MMddyyyy") $strNewDir = "$strTargetDir\$strFileDate" If (Test-Path $strNewDir) { Copy-Item $log $strNewDir } Else { New-Item -ItemType Directory $strNewDir Copy-Item $log $strNewDir } } # GET ALL OF THE DATE DIRECTORIES CREATED [array]$arrDateDirs = Get-ChildItem -Directory $strTargetDir # GO THROUGH EACH DIRECTORY AND GENERATE THE WINDOWSUPDATE.LOG ForEach ($DateDir in $arrDateDirs) { $strFullName = $DateDir.FullName [array]$arrETLs = Get-ChildItem "$strFullName\WindowsUpdate*.etl" [int]$ETLCount = $arrETLs.Count # SINCE TRACEFMT.EXE CAN ONLY HANDLE 15 FILES AT A TIME, BREAK LIST UP INTO GROUPS OF 15 # ROUNDING UP TO NEXT WHOLE NUMBER (16 WOULD BE 2 GROUPS, 46 WOULD BE 4 GROUPS, ETC.) [single]$NumGroups = [math]::Ceiling($ETLCount/15) # INITIALIZE COUNTERS [int]$intGrpCtr = 1 [int]$intETLCtr = 0 # PROCESS THE GROUPS OF 15 ETL FILES NOW While ($intGrpCtr -le $NumGroups) { New-Variable -Name "tmpVar$intGrpCtr" $tmpVar = Get-Variable -name "tmpVar$intGrpCtr" # TAKE EACH GROUP OF 15 THROUGH TRACEFMT NOW While (($intETLCtr -lt (15 * $intGrpCtr)) -and ($intETLCtr -lt $ETLCount)) { $curETL = ($arrETLs[$intETLCtr]).Name $tmpVar.Value += "$CurETL " $intETLCtr++ } # DO THE TRACEFMT COMMAND NOW WITH TMPVAR HOLDING THE 15 ETLS IN THE LIST Set-Location $DateDir.FullName [string]$strLogList = $tmpvar.Value # CREATE SCRIPTBLOCK TO EXECUTE THE COMMAND $sbTrace = $ExecutionContext.InvokeCommand.NewScriptBlock("$TraceFMTPath\TraceFmt.exe -o .\windowsupate$intGrpCtr.log $strLogList -r $SymbolPath") Invoke-Command -ScriptBlock $sbTrace # CLEAR ALL USED VARIABLES HERE SO THEY DON'T CAUSE ISSUES NEXT TIME THROUGH THE LOOP Remove-Variable -name "tmpVar$intGrpCtr" $intGrpCtr++ $tmpVar = $null } }
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.