My WiX bundle behaves very badly on a specific XP machine (x86). It stalls for six minutes during the "initializing" phase (before any bundled installers are run). From the logs it seems extremely likely it is due to the dodgy state of windows update on the machine:
[090C:0FC0][2018-03-27T19:31:17]i358: Pausing automatic updates.
[090C:0FC0][2018-03-27T19:37:23]w308: Automatic updates could not be paused due to error: 0x80080005. Continuing...
[090C:0FC0][2018-03-27T19:37:23]i360: Creating a system restore point.
I am using WiX v3.10 to make the bundle. I can find very similar situations from google search but the solution always revolves around updating the target machine. I need this installer to work as expected regardless. When I test a regular msi on the same machine it goes through fine.
Is there any way I can mitigate this issue? E.g. can I stop the WiX bundle from trying to pause windows update or something similar? The fact that the installer doesn't even notify what the issue is is extremely problematic, any user is likely to be confused.
The whole point of this WiX installer is to make an install package portable and simple but this actually seems LESS portable than just the msi...
Update: Also tried building the bundle with WiX 3.11 but got same problem. Though now it produces an actual error rather than installing regardless, which I suppose is an improvement.
UPDATE: after looking in the WiX source code it looks like WiX's Burn feature is making a few calls to Microsoft.Update.AutoUpdate
(%SystemRoot%\System32\usoapi.dll
- %SystemRoot%\SysWOW64\wuapi.dll
) and a few other COM objects here and there.
See towards the bottom (screenshot) for a hot COM tip to quickly get an overview of different COM object models.
It must be this AutoUpdate call which hangs causing a timout along the lines of what is described in this blog. I believe you can find the exact source code location by searching for hr = WuaPauseAutomaticUpdates();
in the elevation.cpp WiX Burn source file (Github link). The actual calls to the COM object are in wuautil.cpp.
I am not familiar with the Windows Update Agent Object Model, but I suppose you could try to call the Pause
function in a test VBScript just to see what kind of error you get on your problem system (if any). I can't see how you would get anything but a lockup on your problem system, so maybe try first on your main box? This is obviously at your own risk. I would assume a reboot or a call to Resume
will continue the process as normal. I also see a call to SystemInformation.RebootRequired
in the C++ code, which I have also added to the VBScript:
Set autoupdate = CreateObject("Microsoft.Update.AutoUpdate")
autoupdate.Pause()
MsgBox Err.Number & " " & Err.Description
Set sys = CreateObject("Microsoft.Update.SystemInfo")
MsgBox sys.RebootRequired
' autoupdate.Resume() ' Enable to resume AutoUpdate
Set sys = Nothing
Set autoupdate = Nothing
Let's face it: Windows Update is broken on your XP machine - isn't it? Maybe the WiX guys can add a shorter timeout? I am not sure what is better - 1)
to shorten the timeout, 2)
to remove the whole call or 3)
to just bomb out telling the user that Windows Update is broken? Frankly the latter would probably alert the user to something very serious (often malware).
UPDATE: as you state yourself, Windows Update is almost certainly broken on this particular machine. I would try the MSI properties suggested below for testing, and then zap Windows Update as suggested here (same link as below) (techical).
But wait, maybe a malware check is in order, before wasting time on anything else?
File
=> Show Details for All Processes
and then elevate to get to scan system processes as well. Now click "System" to scan drivers for example (*.sys files). Nicely formatted and phrased question BTW. And just for reference: Sysinternals.
I have never seen this, but I have seen some MSI files suddenly pausing for a long time whilst installing whereas they would install quickly during test installs just minutes before.
My guess is that this could be related to system restore and the creation of a restore point at certain "intervals". I am not sure what algorithm is used to determine when such a restore point is created and not, but I wrote an answer many years ago on the issue of speeding up MSI installations: How can I speed up MSI package install and uninstall?
As you will see, you can disable the creation of a restore point for your setup by setting an appropriate command line involving the property MSIFASTINSTALL (and a few other tweaks - please just read the linked serverfault.com answer). I would try this to see if your setup stops locking up / hanging.
Some hits from the web:
I would first try the MSI properties mentioned as a "workaround" above, and if that doesn't work, I would try to see if fixing Windows Update as explained in the link directly above works. Crucially I would also let Windows Update complete its task of installing all available updates before running your bundle again.
I don't like to recommend commercial tools, but we all need some quick tricks and quick wins at times - which is what this is about. Get hold of VbsEdit and use its light weight object browser to quickly see details from any COM object model. Just do a CreateObject
and you will instantly see the object model in the object browser to the right in the application window (View => Object Browser
if it is not there).
Just type in something like this:
Set installer = CreateObject("WindowsInstaller.Installer")
I find this to be a time-saver when I need to deal with legacy COM stuff and Visual Studio is very sluggish. I just have the VbsEdit trial version, and it allows basic editing. And let's throw in a rant: why on earth do they not make a Javascript version? I am missing something - as usual :-).
Throwing in a second screen shot to show a more interesting object model information tidbit:
Should you want to try it, here are some other CreateObject statements you can try:
Set autoupdate = CreateObject("Microsoft.Update.AutoUpdate")
Set fso = CreateObject("Scripting.FileSystemObject")
Set scriptshell = CreateObject ("WScript.Shell")
Set dictionary = CreateObject("Scripting.Dictionary")
Set shell = CreateObject("Shell.Application")
User contributions licensed under CC BY-SA 3.0