2.5 C
New York
Monday, January 8, 2024

Logging and Error Dealing with Finest Practices for Automating Home windows Replace Installs (MSU) with wusa.exe (And For Logging Any Known as Course of)


Automation of Home windows Updates is mostly completed by calling wusa.exe towards a .MSU file. When wusa.exe experiences a failure the messages are sometimes obscure and exhausting to diagnose. The underlying error messages, nevertheless, are incessantly simple to know and resolve.

The key is to have wusa.exe do verbose logging in it’s customary exported home windows occasion format after which use the PowerShell occasion message CMDLets to question that log – routinely, everytime you might have an error.

Though centered on making use of updates with wusa.exe, this text accommodates most of my logging greatest practices for automation coding when calling automated sub-processes.

Every thing on this publish is useful even in case you are the one one who will ever study the logs of the automation you construct. Nevertheless, you’ll hear a persistent theme on this publish of the way it helps “others”. Since I can keep in mind, I’ve constructed utility instruments which can be leveraged by others or supported by a separate assist staff. In these circumstances, investments like those mentioned on this article, have a really excessive “Group ROI” in addition to assist to protect the automation developer’s time towards pointless escalation incidents.

There are a number of attributes of wusa.exe execution that make consideration to logging all of the extra useful:

  1. wusa.exe crucial errors don’t generate terminating errors in PowerShell
  2. For a similar root trigger, wusa.exe exit codes are completely different from logged error codes
  3. For a similar root trigger, logged error codes are in decimal whereas those which may show interactively when working Home windows Replace GUI are in hex (however at the very least the identical quantity when transformed).

0x80240017 / 2149842967 / -2145124329 (Wusa.exe exit code) Log: “Home windows replace couldn’t be put in due to error 2149842967” Interactive “The replace isn’t relevant to your laptop” => Painful – first the logged message isn’t very useful. Second, you may get this message should you merely wouldn’t have the proper stipulations – should you can’t discover the frequent causes of not assembly stipulations for the precise replace you’re making use of, then you must dissect the home windows replace to learn it’s stipulations part. See “Dissecting Home windows Replace Packages” beneath.

0x80070422 / 2147943458 / 1058 (Wusa.exe exit code) – Home windows Replace Can’t Examine For Updates => Normally means the Home windows Replace Service is stopped – watch out that it’s not stopped for a sound purpose (e.g. different lengthy working deployment automation is presently underway.)

0x80070002 / 2147942402 / 2 (Wusa.exe exit code) – The system can’t discover the file specified. => The .MSU file isn’t obtainable on the location handed to wusa.exe. Additionally happens in different circumstances.

Extra Frequent Errors

When coding automation I an enormous advocate of verbose logging for all the pieces my automation invokes (in addition to having the automation do it’s personal logging) – and to a activity particular location when logs will be directed to a customized location.

That is for a number of strategic causes:

  1. Verbose sub-process logging is tremendous helpful in manufacturing environemnts, nevertheless, it’s jaw dropping how usually verbose logging helps me whereas growing automation code.
  2. As soon as the answer is in manufacturing, I get much less calls as a result of those that run into issues with my work can incessantly clear up the issue on their very own when the correct logging knowledge is in entrance of them. That makes me, my staff and different groups quicker and extra productive.
  3. After I get calls, I can ask for the logs that I already know exist. That makes me, my staff and different groups quicker and extra productive 🙂
  4. In manufacturing (or take a look at or dev) there isn’t a want to try to breed the issue AFTER logging has been enabled – so when you’ve got a uncommon transient downside, you get most data on each occurence. That makes me, my staff and different groups quicker and extra productive 🙂
  5. I’ve come throughout many, many fascinating edge circumstances just by having verbose logging on for improvement. That enables me to bake in dealing with of particular points when merited or to at the very least doc them and their decision.

Whereas wusa.exe logging is very helpful, there a pair nuances about it which can be difficult to navigate – particularly in case you are beginning to use the parameter for the primary time.

  1. The log output format is “Exported Occasion Log” – in different phrases the identical sort of file as should you exported home windows occasion logs utilizing the occasion log viewer. Nice confusion outcomes should you give it a .log extension since you and others will attempt to open it in a textual content editor. A bunch of the productiveness advantages I search are misplaced if people in addition to myself can’t view the contents with out contacting me. To get round this I merely identify the log file with the exported occasion file extension. This causes it to open within the occasion log viewer if double-clicked and it additionally cues different folks that the file isn’t a easy textual content file. I additionally like to make use of a file identify that communicates quite a lot of meta knowledge.

    The beneath instance tells precisely what replace and precisely when the set up occurred. If folks would possibly ship me these in electronic mail, I’d most likely additionally embed the pc identify, as a result of having the incorrect log despatched to me is a frequent expertise that makes us all much less productive:

    $logfilename = "$env:PUBLICLogsApplyPSH5PowerShell-Set up-W2K12-KB3191565-x64-$(Get-date -format 'yyyyMMddhhmmss')-Log.evtx"
    
  1. The command line parameter is fussy. Not like the opposite parameters for wusa.exe it:

    1. MUST have a colon after it,
    2. should not have whitespace after the colon,
    3. should be enclosed in quotes if there are areas within the file identify
    4. If you happen to break any of those guidelines, home windows replace typically runs with out errors, it simply doesn’t generate a log.

    The above listing is an mixture throughout a number of variations of Home windows – so not all of those sensitivities is perhaps current in a given model of Home windows.

    Right here is an instance of what I take advantage of to keep away from these issues:

    
    wusa.exe W2K12-KB3191565-x64.msu /quiet /norestart /log:"$logfilename"
    
    
    $wusaswitches = "/quiet /norestart /log:`"$logfilename`""
    wusa.exe W2K12-KB3191565-x64.msu $wusaswitches
    

Along with being an enormous advocate of logging of referred to as processes, I’m an enormous advocate of verbose logging for my very own automation. It’s merely thoughts boggling what number of instances I discover this truncates the basis trigger dedication section. I’ll obtain a log and instantly discover issues like:

  1. The incorrect model of the automation code has been used.
  2. Incorrect parameters have been used to name the automation code.
  3. Incorrect parameters have been used to name the sub-process.
  4. The code can’t discover one thing which must be a typical a part of each surroundings it was designed to run in.
  5. Precisely what generated “Entry Denied”.

This makes me extra productive 🙂

Nevertheless, one other large purpose I need to log the truth that I’m doing detailed logging on a sub-process is for different professionals to take discover, study that log and incessantly clear up the issue on their very own – which makes each of us extra productive.

Finest Practices for Logging The Log Location (and the Calling Command Line)

  1. After I do verbose logging of one thing like wusa.exe I need to floor that truth within the automation log in order that others utilizing the work will discover that there’s extra detailed logging on a particular name obtainable. By making certain that verbose log location for subprocesses are logged within the prime stage log, I’ll assist others to observe the chain of obtainable forensic knowledge in hopes they will clear up the issue.
  2. I log the sub-process log location on a regular basis, not simply if there may be an error. It’s because there are conditions the place an error is thrown someplace else within the script, however these verbose logs reveal the issue or result in insights that reveal the issue.
  3. I additionally be sure that I Log the precise command line used to name the subprocess. When doing this it’s useful to have saved the command line to run in a variable and use the variable for the precise name in addition to the log message. If the identical variable isn’t used, the log can find yourself being deceptive once you replace the precise command however overlook to search out and replace the logging strains to replicate that replace.
  4. Normally it’s good type to additionally emit your log messages to the console as a result of if the code runs beneath any sort of orchestration – that orchestration captures all console output. So for instance, if somebody is working my code beneath AWS Cloud Formation – something emitted within the console is caught up into the overall Cloud Formation log – which eliminates yet one more step within the chain of logs to be adopted.
  5. It’s best to do that logging earlier than calling the sub-process – then in case your name causes a catastrophic failure – the log will comprise data on the final name made by the automation code (which possible prompted the failure whether it is reproducible).

Finest Practices for Logging Folder Names and Log File Names

At any time when attainable I log to system folder (non-user profile) devoted to the automation activity that’s working and use a date time serialized string within the identify, amongst different issues this helps with:

  1. with troubleshooting discovery of the logs associated to the automation (related logs in the identical folder)
  2. avoids challenges discovering logs when run beneath completely different consumer contexts (run beneath SYSTEM context or a particular consumer profile for a logged on service)
  3. avoids getting eliminated in automated temp clear up.
  4. can choose a location that each course of can write to and each course of and logged on technician can learn from.
  5. distant entry to a standardized “logroot” is straightforward to setup as a result of it’s in a recognized location and will be shared as learn solely.
  6. Serialization of Folder and/or File: Guaranteeing that a number of subsequent runs of the identical automation do NOT overwrite one another – overwritten logs complicate troubleshooting as you by no means know in case you are wanting on the actual invocation that prompted the issue.
  7. Serialization of Folder and/or File: Higher date time correlation when looking for logs.
  8. Serialization of Folder: Permits cumulative logs for logging mechanisms that overwrite a beforehand current log by default.
  9. Serialization of File: Communicates extra meta knowledge when the log is shared with others out of the context of the folder (e.g. electronic mail, copy to community).

A definite draw back to a customized folder moderately than a temp folder is that that you simply often must examine for the folder and create it earlier than you begin logging to it. A draw back to serializing log folder names in and file names in a customized folder that logs can accumulate indefinitely.

$env:public is an surroundings variable that factors to the general public profile – which all customers have write entry to. Though this folder is beneath the consumer profile root on many methods, it’s not a consumer folder – there isn’t a “public” consumer. It’s used for something that every one customers ought to see and have entry to. A subfolder of the $env:public folder is usually a nice standardized log location, for instance $env:publiclogs

As per the [Testable Reference Pattern Manifesto] (https://MissionImpossibleCode.io/publish/back-to-basics-testable-reference-pattern-manifesto-with-testable-sample-code/) all the beneath code has been examined. Additionally it is obtainable in a repository to assist keep away from issues when copying and pasting from internet pages: [MissionImpossibleCode] (https://gitlab.com/missionimpossiblecode/MissionImpossibleCode)

Totally Serialized Instance of Log Naming (logs by no means overwritten – retains historic runs)

$LogRoot = "$env:PUBLICLogs" 
$SerializedStringForThisRun = $(Get-date -format 'yyyyMMddhhmmss')  
$LogFolder = "$LogRootInstallPSH5-$SerializedStringForThisRun"  
New-Merchandise -ItemType Listing $LogFolder -Drive -ErrorAction SilentlyContinue | Out-Null 
$logfilename = "$logfolderPowerShell-Set up-W2K12-KB3191565-x64-$SerializedStringForThisRun-Log.evtx"  

$wusaswitches = "/quiet /norestart /log:`"$logfilename`""

Write-Host "Working Home windows Replace with the next command which generate a verbose log at: $logfilename"  

Write-Host "Initiating command: wusa.exe W2K12-KB3191565-x64.msu $wusaswitches"

$ResultObject = start-process "wusa.exe" -ArgumentList "$pwdW2K12-KB3191565-x64.msu $wusaswitches" -Wait -PassThru

Non-serialized Instance of Log Naming, reset logs to wash everytime (doesn’t retain historical past)

$LogRoot = "$env:PUBLICLogs"
$LogFolder = "$LogRootInstallPSH5"
If (Check-Path $LogFolder) {Take away-Merchandise $LogFolder -Recurse -Drive -ErrorAction SilentlyContinue}
New-Merchandise -ItemType Listing $LogFolder -Drive -ErrorAction SilentlyContinue | Out-Null
$logfilename = "$logfolderPowerShell-Set up-W2K12-KB3191565-x64-Log.evtx"

$wusaswitches = "/quiet /norestart /log:`"$logfilename`""

Write-Host "Working Home windows Replace with the next command which generate a verbose log at: $logfilename"  
Write-Host "Initiating command: wusa.exe W2K12-KB3191565-x64.msu $wusaswitches"

$ResultObject = start-process "wusa.exe" -ArgumentList "$pwdW2K12-KB3191565-x64.msu $wusaswitches" -Wait -PassThru

The beneath snippets present numerous methods of retrieving and doubtlessly appearing upon the messages generated by wusa.exe.

You may creatively combine a few of these collectively – for example, all the time re-logging discovered warnings and errors – however solely taking motion if ther are literally errors.

At all times Present All Messages in Log

This code all the time re-logs the detailed warnings and errors from the home windows uupdate log – it is a good basic follow for debugging associated errors in addition to serving to with messages which can be classfied as “Warnings” by home windows replace, that are basically errors to your deployment situation.

$WarningMsgs = 3
$ErrorMsgs = 2

$LogRoot = "$env:PUBLICLogs"
$SerializedStringForThisRun = $(Get-date -format 'yyyyMMddhhmmss')
$LogFolder = "$LogRootInstallPSH5-$SerializedStringForThisRun"
New-Merchandise -ItemType Listing $LogFolder -Drive -ErrorAction SilentlyContinue
$logfilename = "$logfolderPowerShell-Set up-W2K12-KB3191565-x64-$SerializedStringForThisRun-Log.evtx"
$wusaswitches = "/quiet /norestart /log:`"$logfilename`""

Write-Host "Working Home windows Replace with the next command which generate a verbose log at: $logfilename"  
Write-Host "Initiating command: wusa.exe W2K12-KB3191565-x64.msu $wusaswitches"

$ResultObject = start-process "wusa.exe" -ArgumentList "$pwdW2K12-KB3191565-x64.msu $wusaswitches" -Wait -PassThru

$LogMessagesOfConcern = @(Get-WinEvent -Path "$logfilename" -oldest | the place {($_.stage -ge $WarningMsgs) -AND ($_.stage -le $ErrorMsgs)})
If ($LogMessagesOfConcern.depend -gt 0)
 out-string 

Utilizing the Existence of an Error within the Verbose Log

The code depends on the home windows replace to precisely report errors after which take into account that there’s a downside provided that that’s true. A draw back to this code is that it’ll not seize malformed wusa.exe command strains or a non-existent .msu.

$WarningMsgs = 3
$ErrorMsgs = 2

$LogRoot = "$env:PUBLICLogs"
$SerializedStringForThisRun = $(Get-date -format 'yyyyMMddhhmmss')
$LogFolder = "$LogRootInstallPSH5-$SerializedStringForThisRun"
New-Merchandise -ItemType Listing $LogFolder -Drive -ErrorAction SilentlyContinue | Out-Null
$logfilename = "$logfolderPowerShell-Set up-W2K12-KB3191565-x64-$SerializedStringForThisRun-Log.evtx"
$wusaswitches = "/quiet /norestart /log:`"$logfilename`""

Write-Host "Working Home windows Replace with the next command which generate a verbose log at: $logfilename"  
Write-Host "Initiating command: wusa.exe W2K12-KB3191565-x64.msu $wusaswitches"

$ResultObject = start-process "wusa.exe" -ArgumentList "$pwdW2K12-KB3191565-x64.msu $wusaswitches" -Wait -PassThru

$LogMessagesOfConcern = @(Get-WinEvent -Path "$logfilename" -oldest | the place {($_.stage -ge $ErrorMsgs) -AND ($_.stage -le $WarningMsgs)})
$LogErrorsOnly = @(Get-WinEvent -Path "$logfilename" -oldest | the place {$_.stage -eq $ErrorMsgs})

If ($LogErrorsOnly.depend -gt 0)
 out-string)

Including Strive / Catch – Simply Show Errors and Warnings

Strive/Catch must be used to seize exceptions that occur as a result of wusa.exe can’t be discovered or began in any respect.

$ErrorActionPreference = 'Cease'
$LogRoot = "$env:PUBLICLogs"
$SerializedStringForThisRun = $(Get-date -format 'yyyyMMddhhmmss')
$LogFolder = "$LogRootSet up PSH5-$SerializedStringForThisRun"
New-Merchandise -ItemType Listing $LogFolder -Drive -ErrorAction SilentlyContinue
$logfilename = "$logfolderPowerShell-Set up-W2K12-KB3191565-x64-$SerializedStringForThisRun-Log.evtx"

$WarningMsgs = 3
$ErrorMsgs = 2

$wusaswitches = "/quiet /norestart /log:`"$logfilename`""

Write-Host "Working Home windows Replace with the next command which generate a verbose log at: $logfilename"  
Write-Host "Initiating command: wusa.exe W2K12-KB3191565-x64.msu $wusaswitches"

Strive {
  $ResultObject = start-process "wusa.exe" -ArgumentList "$pwdW2K12-KB3191565-x64.msu $wusaswitches" -Wait -Passthru
  Write-Output "Return code is: $($ResultObject.ExitCode)"
  If (Check-Path "$logfilename")
  {
    $LogMessagesOfConcern = @(Get-WinEvent -Path "$logfilename" -oldest | the place {($_.stage -ge $ErrorMsgs) -AND ($_.stage -le $WarningMsgs)})
    If ($LogMessagesOfConcern.depend -gt 0)
     out-string 
  }
}
catch {
  Throw $_.Exception
}

The next code reveals tips on how to take motion relying on the CONTENT of the error within the verbose home windows replace / wusa.exe log. The motion on this case is solely to offer a extra significant error – but when the error is recoverable, you need to use the identical code block to take motion.

$ErrorActionPreference = 'Cease'
$LogRoot = "$env:PUBLICLogs"
$SerializedStringForThisRun = $(Get-date -format 'yyyyMMddhhmmss')
$LogFolder = "$LogRootSet up PSH5-$SerializedStringForThisRun"
New-Merchandise -ItemType Listing $LogFolder -Drive -ErrorAction SilentlyContinue
$logfilename = "$logfolderPowerShell-Set up-W2K12-KB3191565-x64-$SerializedStringForThisRun-Log.evtx"

$WarningMsgs = 3
$ErrorMsgs = 2

$wusaswitches = "/quiet /norestart /log:`"$logfilename`""

Write-Host "Working Home windows Replace with the next command which generate a verbose log at: $logfilename"  
Write-Host "Initiating command: wusa.exe W2K12-KB3191565-x64.msu $wusaswitches"

Strive {
  $ResultObject = start-process "wusa.exe" -ArgumentList "$pwdW2K12-KB3191565-x64.msu $wusaswitches" -Wait -Passthru
  Write-Output "Return code is: $($ResultObject.ExitCode)"
  If (Check-Path "$logfilename")
  {
    $LogMessagesOfConcern = @(Get-WinEvent -Path "$logfilename" -oldest | the place {($_.stage -ge $ErrorMsgs) -AND ($_.stage -le $WarningMsgs)})
    If ($LogMessagesOfConcern.depend -gt 0)
    {
      Write-Host "Discovered the next error(s) and warnings within the MSU log `"$logfilename`""
      $LogMessagesOfConcern | Format-Listing ID, Message | out-string | write-host
      
      If ([bool]($LogMessagesOfConcern | the place {$_.message -ilike "*error 2147943458*"}))
        {
          Write-warning "Service couldn't be began, trying to repair this case."
          If ((get-service wuauserv).Starttype -ieq 'Disabled')
          {
            Write-warning "The Home windows Replace Server was disabled, renenabling..."
            Set-Service wuauserv -StartupType 'Handbook'
            
          }
        }
        If ([bool]($LogMessagesOfConcern | the place {$_.message -ilike "*error 2149842967*"}))
        {
          Write-warning "The replace isn't relevant to this laptop - potentialities causes embrace: a prerequisite is lacking or the replace isn't for this working system."
        }
    }
  }
}
catch {
  Throw $_.Exception
}

That is most incessantly completed to try to know the stipulations or OS focusing on of a given replace so as to perceive why it will get the error 0x80240017 / 2149842967 / -2145124329.

New-Merchandise $env:PUBLICLogsApplyPSH5updatefiles -ItemType Listing
broaden W2K12-KB3191565-x64.msu -F:* $env:PUBLICLogsApplyPSH5updatefiles
Get-Content material $env:PUBLICLogsApplyPSH5updatefiles*.txt

This code is used within the PowerShell for Home windows Chocolatey bundle. It’s used to floor higher particulars about why the ugprade failed.

This bundle has been put in over 1.1 million instances – so exposing the underlying errors for others to resolve on their very own guards my time and retains me much more productive 😉

Chocolate Bundle for PowerShell for Home windows (see the ‘catch’ assertion close to the underside of this script): https://github.com/DarwinJS/ChocoPackages/blob/grasp/PowerShell/v5.1/instruments/ChocolateyInstall.ps1

The beneath code’s main house is on the next repository – the place it is perhaps improved upon in comparison with the beneath. Additionally it is safer to make use of the code from the repo moderately than copy and paste from this publish: https://gitlab.com/missionimpossiblecode/MissionImpossibleCode

0x80070003 / 2147942403 – The system can’t discover the file specified. => The .MSU file isn’t obtainable on the location handed to wusa.exe. Additionally happens in different circumstances. Home windows Replace Troubleshooter

0x800705B4 / 2147943860 => Timeout Interval Expired. Troubleshooting Information, Home windows Replace Troubleshooter

0x8024200B / 2149851147 => A {hardware} replace (driver) was not capable of be put in. Home windows Replace Troubleshooter

0x80070020 / 2147942432 = The method can’t entry the file as a result of it’s being utilized by one other course of => Home windows replace is unable to replace particular information as a consequence of locking or antivirus. Troubleshooting Information, Home windows Replace Troubleshooter

0x80073712 / 2147956498 – The Home windows Replace element manifest is corrupted. Troubleshooting Information, Home windows Replace Troubleshooter

0x80004005 / 2147500037 – Corrupt or lacking information within the OS. Reseting Home windows Replace Parts, Home windows Replace Troubleshooter

0x8024402F / 2149859375 – home windows replace is having bother contacting Microsoft servers – could possibly be community settings.

0x80070643 / 2147944003 – issues putting in .NET framework replace.
Troubleshooting Information, Home windows Replace Troubleshooter

Complete Home windows Replace Error Listing



Supply hyperlink

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles