Vista: Windows Update Error 80070011 Semi-Automated Fix

In January, I showed you how to [url=http://moblog.wiredwings.com/archives/20080113/Vista-and-XP-Dual-Boot-Adventures….html]move your program files and your profile folder to a different partition[/url] using robocopy and mklink. With NTFS junctions, you (and your programs) can transparently use the folders on your C drive, while the actual data lies someplace else.

Unfortunately, today, some Windows Updates where shipped that try to install on every reboot, but fail with error code 80070011. Using Google[url=http://www.scroogle.org/cgi-bin/nbbw.cgi]Scroogle[/url], I quickly [url=http://forums.techarena.in/showthread.php?t=697961]found out why[/url] (and how to fix it manually).

Cause: If files cannot be replaced because they’re open, updates write XML commands to \SystemRoot\WinSxS\pending.xml (usually C:\Windows\WinSxS\pending.xml, unless you’ve installed Windows to a different partition). This file will be processed on reboot. To replace files, updates create hard links at the destination, like this:

[code]<HardlinkFile source=”\SystemRoot\WinSxS\amd64_microsoft-windows-ie-internetexplorer_31bf3856ad364e35_6.0.6000.16609_none_89a35f80d52d451d\iexplore.exe” destination=”\??\C:\Program Files\Internet Explorer\iexplore.exe”/>[/code]

This will fail if “Program Files” is on a different partition, as files can only be hard linked within the same partition. I highly doubt that Microsoft will ever fix this, because moving program data to a different partition is not officially supported.

Workaround: If you don’t want to move your program files back to C: (like me), there seems to be only one way to fix this: By copying the updated files the the same partition as the real program folders, and by changing all HardlinkFile references to this new location, it will work. [url=http://forums.techarena.in/showthread.php?p=2950983#post2950983]alantangcs[/url] posted a nice step-by-step guide on how to edit pending.xml (you have to change ownership of the file first).

Because I don’t expect this to be the last time an update tries to change Program Files, I wrote a little script that does most of the work: It will provide a copy of pending.xml with all necessary replacements and copy the files to a directory called “WUTemp” on the same partition as your real program files. If you don’t supply the real location of your program files by command line, the script will ask for it.

A slightly easier workaround might be to replace the affected HardlinkFile commands by CopyFile (not sure if it exists) or MoveFile (exists, but I don’t know how it reacts if the target already exists). That way, the files can stay in WinSxS. I haven’t tried this, and be warned: If you mess with pending.xml and Vista doesn’t boot, it won’t even boot in Safe Mode. Try in a VM or keep some recovery disk handy.


This script in the current design will only work on Vista x64 if both “Program Folder” and “Program Folder (x86)” are at the same (real) location.

[geshi lang=NSIS]echo “WUfix 80070011 for junctioned Program Files directory, by Moritz Bartl ( http://www.wiredwings.com/ ). Public domain. Version 1.0 – 2008.03.01”
echo “Use at your own risk!! READ BLOG ENTRY/README.TXT first!”
echo “This script will not damage anything without your manual help.”
echo “”
# either program files path was supplied by command line, or ask user
if ($Args.Count -lt 1) {
echo “Enter the NEW path of your program folder including drive letter [D:\Program Files]: “;
$program_files = $Host.UI.ReadLine();
if ($program_files -eq “”) { $program_files = “D:\Program Files”; }
} else {
$program_files = [string]$Args[0];
}
# remove trailing slash
if ($program_files.EndsWith(“\”)) {
$program_files = $program_files.Substring(0, $program_files.Length-1);
}
# determine location where update files are copied to, on the same drive as the relocated Program Files folder
$drive_letter = $program_files[0];
$wutemp = “${drive_letter}:\WUTemp\”;
$file = “$env:systemroot\WinSxS\pending.xml”;
$destination = “${wutemp}pending.xml”;
$pattern = new-object System.Text.RegularExpressions.Regex ‘“;
## STARTING HERE, THE ACTUAL FUN BEGINS!
echo “”
echo “Please wait…”
# create/replace $destination
$destination =new-item -ItemType file -force $destination
# open pending.xml and do actual pattern matching/replacing
# extract source files to copy later
$pending = Get-Content $file;
$matchCount = 0;
$sources = @();
for ($i = 0; $i -lt $pending.Count; $i ++) {
$line = $pending[$i];
if ($line -match $pattern) {
$source = $matches[“source”];
$sources += ,$source;
$matchCount++;
$line = [regex]::Replace($line, $pattern, $replacement);
$pending[$i] = $line
}
}
echo “”
# if there were matches, write the new pending.xml to the “temp” directory
# and copy all files that will be hardlinked to the new “WUtemp” directory
# on the same drive as your relocated program folder
if ($matchCount -gt 0) {
Add-Content $destination $pending
$winsxs = “$env:systemroot\WinSxS\”;
echo “$matchCount HardlinkFile references found and replaced. New pending.xml is located at $destination. Validate if everything is okay, then copy it to $winsxs (first, you have to take ownership of the original file there; a backup copy will not hurt).”;
echo “Now, I’ll try to copy the update files. If anything fails here, your update will probably fail, too, if you don’t manually copy the files.”
foreach ($source in $sources) {
# create destination path if it doesn’t exist
$destination_path = split-path “$wutemp$source”
New-Item -Path $destination_path -ItemType Directory -Force
# copy file; some error checking would be useful here…
$copied_item = Copy-Item “$winsxs$source” “$wutemp$source”
}
} else {
echo “No matches. Leave a comment in my blog if you think this should have done something.”;
}
exit;
[/geshi]

Usage:

0. (Re)start installation of the updates within the Update Manager. Make sure there’s a pending.xml in C:\Windows\WinSxS afterwards, but do not reboot (yet)!

1. Make sure you have [url=http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx]Microsoft PowerShell[/url] installed. Sorry that I’ve used it, but I thought this would be a good opportunity to enhance my programming language knowledge. Feel free to translate to different languages!

2. Execute “powershell” as Administrator (Windows button, search “powershell”, right-click on “Windows PowerShell”, select “Run as Administrator”.

3. Enter “Set-ExecutionPolicy RemoteSigned”. This will allow execution of (unsigned) local scripts, while remote scripts need to be signed.

4. Enter the full path to the script and run it.

5. WUfix will query for your real program folder location (the one where the junctions point to). Enter it, including “Program Files”.

If everything works as expected, you’ll find a new folder “WUtemp” in the root of the same partition as your real program folders. Inside, there’s a new pending.xml , and all files that will to be hard linked. Take ownership of C:\Windows\WinSxS\pending.xml ([url=http://forums.techarena.in/showthread.php?p=2950983#post2950983]step-by-step guide]), copy it to a backup location and replace the original by WUtemp\pending.xml .

Reboot and hope for the best. You can delete the WUtemp folder after the updates were successfully installed.

Does anyone have an idea how to detect the actual target of junctions from within PowerShell? This was one of the reasons why I decided to use it in the first place, but I haven’t found out how. That way, the whole process could be automated.

14 Responses

  1. T says:

    I found your fix to work well with some and mot so well with others. I think i may have found the problem, and this may help with SP1 as well. Some updates delete a file and install a new one so after i am done with the wufix, replace the following line
    DeleteFile path=”\??\C:\Program Files
    with this
    DeleteFile path=”\??\D:\Program Files
    It worked on some of the updates, I will see if it works on all, I am not too familiar with PowerShell or I would write it into the script.

  2. Moritz says:

    Thanks for your input. DeleteFile should work with junctions though?
    The problem with SP1 is that it doesn’t create a pending.xml at all, it just fails to install. I haven’t found the time to dig deeper yet, but a possible way might be to temporarily set up a basic program folder on C again (without actually moving all content), install SP1 and then redirect the program folder again.
    I don’t want to mess around with this on my live system, but SP1 doesn’t install at all in a virtual machine…

  3. T says:

    Ok, so to install SP1 what I did was delete the links. after sp1 installed (sucessfully) I took ownership of Program Files on the destination drive and merged the two. then i wnet through the process of moving it on the C drive to the (OLD) file and remade the links. Everything seems to be working so far.

  4. T says:

    Oh and I forgot, for some reason I had to do updates like 2-3 at a time or they would all fail

  5. rei says:

    Anyone having trouble with IE7?
    It seems not to open Notepad when I click View Source, and I can’t install IE8 using this workaround.

  6. Jiminaus says:

    So far, I’ve found changing the ProgramFilesDir (and CommonFilesDir?)values in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion has fixed the failing updates.
    Doing this also created a hidden PendingFiles folder and my updates are going in here before being hardlinked by the updater during a reboot.
    (Vista Ultimate 64bit SP1)

  7. Spike says:

    Thanks for this page, but unfortunately I’m having a few problems.
    ———
    Step 4 is a little vague for someone who only just found out about Powershell.
    “4. Enter the full path to the script and run it.”
    Should the script have a particular extension, i.e. “.bat”, “.com”, “.cmd”, etc??
    Do I just type in the name of the script to run it? Or is there a “run” command of some kind, such as “exec ./file.bat” or “source joe.sh”?
    ——-
    I’m getting the same 80070011 error, but it’s for KB950759 (Cumulative Security Update for IE7 in Vista) and KB905866 (Update for Windows Mail Junk Email Filter June08).
    When applying some recent updates, I rebooted as usual, not expecting any problems.
    On rebooting it told me the two items above failed, and gave me the opportunity to fix the failed items by trying again. However, there is no “pending.xml” file.
    I’ve cancelled and retried a few times, but I can’t find any file called “pending.xml” in the C:\Windows\WinSxS folder.
    Any ideas? Thanks in advance!
    Cheers,
    Spike.

  8. Moritz says:

    Just type the name of the file inside PowerShell to run the script. It will only work if there’s a pending.xml inside the WinSxS directory (which might both be hidden).
    Maybe it helps to set the actual program folder ‘link’ to the new drive as Jiminaus suggested (Reply #4).
    Good luck! Please tell us as soon as you’ve found a solution.

  9. happyguy says:

    Thanks for the info. Just wanted to let you know this post is broken in IE7 on Vista32 sp1. Thanks for the heads-up about Scroogle.com!

  10. Marc Kirkwood says:

    Whoa, it looks like PowerShell is a rather confusing, ugly mix of [BA]SH and DOS batch scripts… Was there any need for them at all to stick with the nasty -eq/-lt/-gt comparison operators, for instance, when you can manipulate .NET objects in a curly bracket C style mixed with Java-like object.method() syntax? Not to mention the whole new get-content $file stuff, which admittedly looks rather concise, until you see the awkwardly verbose “$destination =new-item -ItemType file -force $destination” statement…
    Anyway, enough about PowerShell! I should learn it at some point though. It’s a bit annoying that even in 2009 with Vista SP1 you still can’t easily move system folders to another partition — I wonder if it’s true that Win7 will start using the Unix-like ~/ shorthand for the user’s home directory, along with a / based tree… Seems unlikely though, a bit of a joke?

  11. Ullrich Fischer says:

    I followed some detailed instructions to replace c:\windows\winsxs with a link to a folder on my e: drive so that I could free up some space on my SSD 60 GB C: drive. Since then updates are failing. I’m wondering if updates have a problem copying themselves to of finding what is in the destination of that link. Is there a registry setting somewhere that needs to be updated to take care of this? I’m getting error 80070011 for any update that I try to install.

  12. Moritz says:

    I cannot recommend to move winsxs and have no solution, sorry. After too much trouble I only move the profile data directory ([url=http://moblog.wiredwings.com/archives/20080729/Windows-Vista-Moving-Program-Files-and-User-Data,-Revisited.html]explained here[/url]) and leave the rest alone.
    It doesn’t help to move winsxs, because all updates replace files on the system partition anyway. Files are NOT COPIED to their destination, but hardlinked, so keeping the winsxs directory on C won’t take more space! I’m not sure what happens if a later update changes the same files, I guess the previous update will stay, but maybe one could find a way to cleanup the directory, which is still better than move it completely.
    So, a solution might be to scan for files inside winsxs that are linked only once, which means they are not in use by the system, and move/delete those files?

  13. Viperus says:

    I changed the program files location in Win7 by using symbolic links.
    However, now the SP1 won’t install, and there’s no way to do it manually since the pending.xml file is huge. Any ideas?

  14. JasonH says:

    I moved my program files, program files (x86), and programdata folders on my Windows 7 x64 ultimate edition workstation and I can’t install some updates, specifically KB958559. I tried the script referenced on this page but when I run the update no pending.xml file is created anywhere under C:\windows\WinSxS. Is there something specific I need to do to force the XML file to get generated so I can run the script?