SOLVED - Slow installation of MSU files using the WUSA.exe

Have you ever experienced slow installations when using the WUSA.exe together with *.MSU files? I did with a number of installations, such as:

  • Microsoft Language Packs -> Multi-Language User Interface (MUI)
  • Microsoft Internet Explorer 11
  • Microsoft Internet Explorer components (Hyphenation, Spelling)
  • Microsoft Internet Explorer 11 Language Packs
  • Various Microsoft hotfixes

 

 

The Solution (short version)

In case you are in a hurry and are not waiting for any blabla, here is the quick version of the solution:

  • Do not use the MSU file to install the software, but instead, extract the MSU file and use the included CAB file instead (not the one called WSUSSCAN.cab, the other one). Use the following command to extract the MSU file:
    expand -f:* "C:\%InstallFile%.msu" %TEMP%
    For example:
    expand -f:* "C:\Temp\Windows6.1-KB2896256-x64.msu" C:\TEMP
  • Then use the following command to install the software:
    dism.exe /online /add-package /packagepath:"%InstallFile%.cab" /quiet /norestart /logpath:"%LogFile%"
    For example:
    dism.exe /online /add-package /packagepath:"C:\Temp\Windows6.1-KB2896256-x64.cab" /quiet /norestart /logpath:"C:\Logs\Install_hotfix_Windows6.1-KB2896256-x64.log"

For more information please continue reading.

The Situation

First of all let's be clear under which circumstances my problem arose:

  • Operating system: Windows Server 2008 R2
  • System deployment tool: Microsoft SCCM 2012 R2
  • Execution script: PowerShell (version 5.0)
  • Execution command in script:
    wusa.exe %InstallFile% /quiet /norestart /log:%LogFile%

The PowerShell wrapper was started by SCCM, which means that it runs under the local System account.

The Problem

The installation of the individual installations took a REALLY long time. For example, an Internet Explorer language pack took up to 25 minutes to install, which under normal circumstances should only take 2 minutes or so. The same goes for the other components. Since I was creating a new golden image for my XenDesktop 7.x workers and I was installing 8 language packs this took about 2 hours! This was unacceptable of course.

The Reason

In my installation packages I used the WUSA.exe to install the software. The WUSA.exe is the Windows Update Standalone Installer. As per Microsoft:

The wusa.exe file is located in the %windir%\System32 folder. The Windows Update Standalone Installer uses the Windows Update Agent API to install update packages. Update packages have an .msu file name extension. The .msu file name extension is associated with the Windows Update Standalone Installer.

Reference: https://support.microsoft.com/en-us/help/934307/description-of-the-windows-update-standalone-installer-in-windows

I have to admit that I am still not 100% sure why the problem arose, but the main cause is for sure related to how the process WUSA.exe works. In the end, I suspect the problem has to do with two things:

  • First of all, as written in the aforementioned Microsoft article, the WUSA.exe "uses the Windows Update metadata in the .msu file to search for applicable updates". This is the first step in the installation process. To me this means that the WUSA process tries to contact either the Windows Update server within our LAN or it tries to reach a Windows Update server on the Internet.
  • Secondly, the SCCM installation runs under the local System account. This account has very limited permissions outside of the local server. It does have sufficient rights to contact the Windows Update server in the LAN, but not to contact Windows Update servers on the Internet.

As I said, I am not 100% sure what caused the delay in the process. Either the WUSA.exe tried to contact servers on the Internet (which it could not) or it tried to find some information on the local Windows Update servers which it could not find. I do not know.

In the end, the WUSA.exe process simply "got stuck" for whatever reason. After 25 minutes or so it (probably) ended in a time-out. Mind you, the installation itself worked fine, but it took a really long time to complete.

The Solution (long version)

In the Microsoft article mentioned in the previous paragraph a potential solution is presented. The solution is to install the MSU files by using the command DISM.exe /Add-Package. However, for some reason, this command did not work on all packages. It worked on the Windows Language packs, but not on IE 11 nor the hotfixes. In the cases where it did not work I received a strange error. But I wanted one method to rule them all.

So I decided to go a slightly different way. You see, DISM can be used to install CAB files as well. As per Microsoft:

Operating system package-servicing commands (DISM) can be used offline to install, remove, or update Windows® packages provided as cabinet (.cab) or Windows Update Stand-alone Installer (.msu) files.

Reference: https://msdn.microsoft.com/en-us/library/hh825265.aspx

So I decided to use the "dism.exe" command to install the CAB file included within the MSU file. These are the steps:

  1. Extract the MSU file using the following command:
    expand -f:* "C:\Temp\%InstallFile%.msu" %TEMP%
    For example:
    expand -f:* "C:\Temp\Windows6.1-KB2896256-x64.msu" %TEMP%
  2. After extraction there will be four files present in your directory: two CAB files, one XML file and one TXT file. The MSU file used in this example included the following files:
    • Windows6.1-KB2896256-x64.cab
    • Windows6.1-KB2896256-x64.xml
    • Windows6.1-KB2896256-x64-pkgProperties.txt
    • WSUSSCAN.cab

    Do NOT use the file called WSUSSCAN.cab. Use the other one. In our example this would be the file Windows6.1-KB2896256-x64.cab.

  3. Use the following command to install the CAB file:
    dism.exe /online /add-package /packagepath:"%InstallFile%" /quiet /norestart /logpath:"%LogFile%"
    For example:
    dism.exe /online /add-package /packagepath:"C:\Temp\Windows6.1-KB2896256-x64.cab" /quiet /norestart /logpath:"C:\Logs\Install_hotfix_Windows6.1-KB2533623-x64.log"

And one last thing. In case you are wondering why I used the "dism.exe" executable within PowerShell instead of the native PowerShell command "Add-WindowsPackage", please remember I was working on Windows Server 2008 R2. Even though PowerShell version 5.0 was installed on the local system, the cmdlets for DISM are only available from Windows 8.1/Windows Server 2012 R2.

Share this post:
Dennis Span on EmailDennis Span on LinkedinDennis Span on Twitter
Dennis Span
Dennis Span
Dennis Span works as a Senior Citrix Architect for a large insurance company in Vienna, Austria. He holds multiple certifications such as CCE-V, CCIA and CCEA. In 2017, Dennis became a Citrix Technology Advocate (CTA). Besides his interest in virtualization technologies and blogging, he loves spending time with his family as well as snowboarding, playing basketball and rowing. He is fluent in Dutch, English, German and Slovak and speaks some Spanish.

15 thoughts on “SOLVED - Slow installation of MSU files using the WUSA.exe

  1. Thank you. I was stuck for days trying to install the Convenience rollup for Windows 7 SP1. Your method finished it in a few hours. Works like a charm. Very nice piece of detective work.

  2. Interesting installation method, i've found that disconnecting the internet will allow an MSU file to install much faster. I'm not sure why the local System account would have access to the LAN but not the Internet, seems like an odd design decision by Microsoft to run it under that if this is the case. Might explain why the updates hang for so long though if they can't actually establish the connection they're trying to do. Will keep this in mind for next time i'm pushing out large updates.

    • Hi Andrew. Thanks for your message. I can believe that disconnecting from the Internet may significantly improve the installation of an MSU file. As I state in the article, the WUSA.exe tries to contact a Windows Update server (at least that is what I assume) before installing the MSU. If there is no Internet connection, the WUSA.exe will quickly realize that a connection to a Windows Update server cannot be established and will therefore start with the installation sooner. At least that is what I assume.

  3. For offline image servicing I don't think DISM performs any of the usual diligence surrounding prerequisite checking. It'll sometimes let you inject a CAB into a WIM that shouldn't work due to that WIM missing some other update. If online servicing is the same way, using DISM to install packages could prove troublesome.

    I plan to test some of this soon since I'm fighting with a 2012R2 installation and MDT as I write this...

  4. Excellent Alternative. My issue with your alternative though is, I am trying to run some custom sequences using SCCM and WUSA but on Server 2008 SP2 - Where DISM does not yet exist.

    Any work arounds for that?

    I can use my SUP as a last resort but, i wanted some smooth TS running WUSA setup as applications for each patch.

  5. Thanks for the info. That looks to sort out an issue where the patches wouldn't install on a few machines. Wrapped the whole thing up in a Powershell script that may be useful to others. Think that an install date of 01/01/1601 may be used to indicate that a reboot is required but if this isn't that case, the reboot message will be incorrect:

    $roots = @("$($ENV:USERPROFILE)\Desktop", "$($ENV:USERPROFILE)\C:\Downloads")
    $copyto = "C:\Temp"

    if (-not (Test-Path $copyto)) {

    mkdir $copyto -ErrorAction SilentlyContinue

    }

    $items = @()

    foreach ($root in $roots ) {
    if ( [System.IO.Directory]::Exists($root) ) {
    $items += get-childitem $root | Where-Object -FilterScript {$_.Name -match '\(KB\d+\)'}
    }
    }

    [regex]$kbreg = "KB\d+"

    foreach ( $item in $items ) {

    $patch = get-childitem $item.FullName -recurse
    $kb = ($kbreg.Match($item.Name)).Value

    if ( $kb ) {

    $installfrom = "$copyto\$kb"

    mkdir $installfrom

    Write-Host "Copying $($patch.Name) to $installfrom"

    expand -f:* $patch.FullName $installfrom
    $patch = get-childitem -path "$installfrom\*kb*.cab"

    Write-Host "$(Get-Date): Installing $($patch.Name)"

    $log = "$installfrom\$($kb).log"
    $patchpath = $patch.FullName
    dism /online /add-package /packagepath:$patchpath /quiet /norestart /logpath:$log

    $hotfix = get-hotfix | Where-Object -FilterScript {$_.HotfixID -eq $kb }
    $reboot = ("required", "not required")[$hotfix.InstallDate -lt (get-date).AddDays( -1 )]
    Write-Host "$(Get-Date): Installation finished. Reboot possibly $reboot."

    }
    }

Leave a Reply

Your email address will not be published.

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.