How to relocate the Package Cache

How to relocate the Package Cache

Rate This
  • Comments 16

Visual Studio can require a lot of space on the system drive. Based on years of data collected from customers’ installations from the Customer Experience Improvement Program, we took advantage of this feature in Burn – the Windows Installer XML (WiX) chainer – to eliminate most errors during repair, servicing, and even uninstall. This was not a popular decision with some customers. For years even I pushed against caching Visual Studio deployment packages because of the impact to drive space as well, but as HDD space increased market studies showed little reason not to cache for the increased reliability of deployment.

We understand, however, that many customers have smaller SSDs and while size will increase and cost decrease over time, some customers are blocked from installing Visual Studio or have little space left over after a successful installation.

I have submitted a feature proposal to WiX to allow control over the Package Cache location, but until then there is a workaround that really highlights some of the virtualization features in Windows.


This practice has received some testing and has been running under load for a reasonable amount of time. While it uses documented features of Windows, this is not an officially supported practice and may leave your machine in a corrupted state should you disconnected the secondary drive or fail to properly secure the folder mount point and its contents.


You can move the contents of the Package Cache to a partition on another drive – copying the ACL and owner, which is very important for both security and because some programs may not trust any ACL or owner that is different than what is expected – and then mount that partition into an empty folder. But rather than dedicate an entire partition on a physical disk – which isn’t always as easy to reconfigure on the fly – we will create a virtual disk (VHD) on another drive.

By creating an expandable virtual disk we can declare a maximum size that can be much larger than necessary – even larger than the host drive itself – but takes up only as much room as necessary and will grow as the content grows. This way, should you ever need to allocate more space you can simply dismount and move the VHD to another disk, then remount it. No need to recopy files.

Mounting a VHD into an empty directory also maintains the mount across reboots – something not currently supported when mounting a VHD for drive access.

System requirements

Support for creating and mounting VHDs was built into Windows Vista with support for VHDs larger than 2TB added in Windows 8 using the newer VHDX format.

Manual walkthrough

To show more in depth how this works – and how you might adapt it for your own use – I will use a couple of built-in programs: diskpart.exe and mountvol.exe. We can also do all this in PowerShell with the right Windows Features enabled but I will cover that in the scripted section.

  1. Open an elevated command prompt.
  2. Run diskpart.exe to start the disk partitioning utility:
  3. Create a large (ex: 1TB), expandable VHD on whatever secondary disk (ex: X:) you prefer with security matching the source directory’s security:
    create vdisk file="X:\Cache.vhd" type=expandable maximum=1048576 sd="O:BAG:DUD:P(A;;FA;;;BA)(A;;FA;;;SY)(A;;FRFX;;;BU)(A;;FRFX;;;WD)"
  4. Select the VHD and create a partition using all available space:
    select vdisk file="X:\Cache.vhd"
    attach vdisk
    create partition primary
  5. Format the volume that was created automatically and temporarily assign a drive letter (ex: P:):
    format fs=ntfs label="Package Cache" quick
    assign letter=P
  6. After exiting diskpart.exe, move any existing per-machine payloads from the Package Cache with security:
    robocopy "%ProgramData%\Package Cache" P:\ /e /copyall /move /zb
  7. Recreate the Package Cache directory and set up the ACL and owner as before:
    mkdir "%ProgramData%\Package Cache"
    echo y | cacls foo /s:"O:BAG:DUD:PAI(A;OICIID;FA;;;BA)(A;OICIID;FA;;;SY)(A;OICIID;FRFX;;;BU)(A;OICIID;FRFX;;;WD)"
  8. Run mountvol.exe without any parameters first and look for the volume name that has the drive letter you assigned to the VHD, then use that with mountvol.exe again to mount that volume into the empty Package Cache directory.
    mountvol "%ProgramData%\Package Cache" \\?\Volume{a525b826-8a0c-11e3-be94-00249b0716f5}\
  9. Run diskpart.exe again and remove the drive letter assignment from the volume (should be in partition 1 of the VHD):
    select vdisk file="X:\Cache.vhd"
    select partition 1
    remove letter=P
  10. Non-boot VHDs are not automatically mounted, so before you reboot you need to make sure the VHD is mounted again whenever the machine is started. Write a simple script for diskpart.exe to execute on startup. If you’re doing this on a laptop, you should edit the scheduled task afterward to allow it to run on batteries.
    echo select vdisk file=X:\Cache.vhd > X:\Cache.txt
    echo attach vdisk >> X:\Cache.txt
    schtasks /create /ru system /sc onstart /rl highest /tn "Attach Package Cache" /tr "%SystemRoot%\System32\diskpart.exe /s X:\Cache.txt"

After exiting diskpart.exe you now have mapped a VHD on another drive into the new Package Cache directory. The VHD will be remounted into the directory whenever the machine is rebooted. If you look at the mount point, you will also see its icon, description, and size are different.

The size reported in Windows Explorer is merely the maximum and not how much space is consumed within the virtual disk. In fact, you probably would care less about that than how much space the VHD itself is consuming. Browse to the folder were you created the VHD (ex: X:\Cache.vhd) and you will see the actual file size.

When bundles have been uninstalled and packages removed from the Package Cache, you can attempt to compact the VHD to reclaim space on the host disk.

  1. Open an elevated command prompt.
  2. Run diskpart.exe:
  3. Select the VHD and attempt to compact it:
    select vdisk file="X:\Cache.vhd
    compact vdisk

Should you ever need to move the file, you can use mountvol.exe to dismount the VHD, copy it to another attached drive, and remount the VHD.

Scripted solution

Once the Hyper-V Module for Windows PowerShell is installed on supported Windows platforms, you can easily script this and execute it on remote machines running an elevated WinRM endpoint. PowerShell is a powerful object-oriented shell that provides for the same compositional techniques of any modern programming language.

I have created an example PowerShell script you can use locally on any Windows 7 machine or newer, or run on remote machines using the Invoke-Command cmdlet.

When bundles have been uninstalled and packages removed from the Package Cache, you can attempt to compact the VHD to reclaim space on the host disk.

  1. Open an elevated PowerShell prompt.
  2. Run the following command to get and optimize (compact) the VHD you passed as a parameter to Move-WixPackageCache.ps1 (ex: X:\Cache.vhd):
    get-vhd X:\Cache.vhd | dismount-vhd -passthru | optimize-vhd -passthru | mount-vhd


Mounting virtual disks hosted on other attached disks can be an effective workaround to reducing space on the system drive. We will continue to explore options for locating more data on the chosen installation drive but there will always be some components that need to be installed to the Windows or Program Files directories. There are some known issues when redirecting those and other directories to another drive other than where Windows is installed, so leaving plenty of space on your system drive is always recommended.

Leave a Comment
  • Please add 4 and 2 and type the answer here:
  • Post
  • Would a junction or symlink eliminate the need for a mount point?

  • @Anthony Frazier, hard links must be defined in the same volume but junctions can be defined across *local* volumes. So if you do have separate local drives (I don't have a USB attached HDD to know if that counts as local) junctions could work but you must still make sure permissions and ownership are set correctly. Some programs do check and may not trust the contents of a directory that do not match its expectations on security.

  • Can I relocate the whole c:\Windows\Installer that same way?

  • Hi dears.

    I reallocate whole of Windows Installer. It seems there isn't any problem and I save 18 GB space in my Windows drive.

    Thanks a lot for this useful post.

    GOD bless u.

  • Here is my 24 GB solution using a small SSD C: drive and 2TB traditional D: drive without mounting VHD drives. No problem so far on my computer, but USE AT YOU OWN RISK.:

    1. MoveDirectory.cmd

    robocopy "C:%~1" "D:\- C -%~1" /e /j /copyall /dcopy:dat /sl /ndl /move

    mklink /J "C:%~1" "D:\- C -%~1"

    2. MoveDirectories.cmd

    call MoveDirectory.cmd "\Program Files\Microsoft SQL Server\100\Setup Bootstrap"

    call MoveDirectory.cmd "\Program Files\Microsoft SQL Server\110\Setup Bootstrap"

    call MoveDirectory.cmd "\Program Files\Microsoft SQL Server\120\Setup Bootstrap"

    call MoveDirectory.cmd "\Program Files (x86)\Microsoft SQL Server\100\Setup Bootstrap"

    call MoveDirectory.cmd "\Program Files (x86)\Microsoft SQL Server\110\Setup Bootstrap"

    call MoveDirectory.cmd "\Program Files (x86)\Microsoft SQL Server\120\Setup Bootstrap"

    call MoveDirectory.cmd "\ProgramData\Package Cache"

    call MoveDirectory.cmd "\Windows\Installer"

    ps.: Save the two batch files, and run the second one in Admin level Command Prompt.

  • Symbolic links do not work: Visual Studio update installer will delete symlink and create folder instead!

  • @Kazi I prefer your method becaus it is easier and more flexible. Any issues so long with the linked folders?

    @Heath, any response from MS about fixing this in the near future? What about VS2015 TP?

    Thanks a million in advance!

    @feeddeadbeef, don't nail me down but I always thought that there is a difference between symbolic links and junctions (aka reparse points). Are you talking from experience here?

  • @Boian, fixing what? The package cache may be large but has resolved far more issues we've had with past releases that were difficult to resolve - especially for end users.

  • It seems like Package Cache solves a problem (insert physical install media) that isn't a problem anymore given the widespread use of .iso install media.  Does package cache solve anything that can't be addressed by the numerous .iso install images I have? Am I simply using 3 times the amount of drive space to install VS (install to program files, package cache and copy of setup iso)?

  • I've been unable to make this work. The command to create the vhd fails with a message saying the security descriptor is not valid. If I create it without the security descriptor, it works, but it seems to cause issues later when I try to uninstall or modify the installation.

    using Windows 8.1 Update 1 x64

  • @Thomas, is your machine domain-joined? If not, that would likely explain it since some of the RIDs are domain-specific.

  • This doesn't seem to work if the path to the .vhd has spaces in it! I think I finally got everything fixed, but it was not mounting the vhd.

    Adding quotes to this line should fix the issue:

    select vdisk file="$VhdPath"

  • Hi Heath,

    This looks great and I've tried your ps1 file. I have two questions:

    1) How can I verify that the VHD is doing it's job? Their is a drive letter assignment but I can't access it. The program data\package cache folder is still in c:\. I installed some packages I've never used before and don't see them going into the c:\ folder. But I unmounted the VHD and installed yet another new tpakage and visual studio didn't complain.

    2) How can I tell where nuget is trying to store & find cached packages?


  • @Julie, I recommend using this approach instead:

    Or go through the manual steps in this blog post and see what was missed.


    I used Kazi's approach. I have a surface dev machine with 128gb C drive and I needed all of the Package Cache folder moved elsewhere. I have discovered a minor glitch though that anyone using that solution should be aware of.

    I moved "C:\ProgramData\Package Cache" to "D:\ProgramData\Package Cache", also "C:\Windows\Installer" to  "D:\Windows\Installer", then made the junction points.

    Everything works great. I've installed new software, and removed existing software. The problem though is if I install one new program immediately after the move, and then uninstall that program, the junction point "C:\ProgramData\Package Cache" is being removed.  This is happening on my Windows 7 machine where I've also used this solution, I'm unsure what will happen on my windows 8 machine.

    The data is still there in "D:\ProgramData\Package Cache", but on my next install it recreates the "C:\ProgramData\Package Cache" as a folder rather than using the junction. Presumably any future install/uninstall that tries to access the data I moved to the D drive will fail at this point.

    The fix is to recreate the junction after running the uninstall that removed it.

Page 1 of 2 (16 items) 12