21

I have installed Hyper-V Server 2012 R2 on a server that had Hyper-V Server 2012. When I did this, the standard Windows.old folder was created. I now would like to remove that folder safely. The standard way to do that with a full GUI would be to use Disk Cleanup, but of course I don't have that option on Hyper-V Server.

Is there a formal way to remove that folder in this scenario? I know if this was Server Core I could install the full GUI including Desktop Experience, but that would be a lot of nonsense just to cleanly remove a folder.

My primary reason for asking, as opposed to just doing rmdir /s or some such, is that the Windows.old folder has a lot of junctions, and I don't want to break anything in the production OS copy as part of doing this.

  • I read cleanmgr.exe can run in the command line... Not sure if this applies to server core or 2012??? – john Oct 12 '13 at 22:16
22

I first tried to copy and run cleanmgr.exe (Disk Cleanup tool), but it has too many dependencies on DLLs which are not present in Core/Hyper-V Server.

So instead I deleted the directory manually.

First I removed all junction points and symbolic links. To do this I used junction.exe from SysInternals. Copy the exe into a directory in your path. I ran it to get a list of all junctions:

c:\tools\junction.exe -s -q C:\windows.old > %temp%\junc.txt

I opened a PowerShell:

start powershell.exe

and ran the following script to find the relevant lines and execute junction.exe again:

 foreach ($line in [System.IO.File]::ReadLines("$env:temp\junc.txt"))
 {
     if ($line -match "^\\\\")
     {
         $file = $line -replace "(: JUNCTION)|(: SYMBOLIC LINK)",""
         & c:\tools\junction.exe -d "$file"
     }
 }

This removed all junction points and the single symbolic link on my system.

back in cmd.exe I now executed three commands to clear permissions and delete all files:

 takeown /F C:\windows.old /R /D Y
 cacls C:\windows.old /T /G Everyone:F
 rd /s /q C:\windows.old

In my test, I installed a new Hyper-V server 2012, then upgraded to 2012 R2, Windows.old is now gone and the system is running fine with all old junction targets intact.

  • What was the contents of junc.Txt? Can you post it to pastebin? I'm curious if anything of interest was linked. – longneck Oct 12 '13 at 22:40
  • pastebin.com/pYBGR4ap has all the relevant lines from junc.txt – Peter Hahndorf Oct 13 '13 at 6:51
  • This appears to have worked fine, thanks! I also now know takeown exists, which I'm slightly embarrassed to admit I didn't know about. – MikeBaz - MSFT Oct 13 '13 at 13:25
  • 1
    Why would one need to manually remove the junction points before deleting the folder? The junction points are stored in the filesystem, so would surely get deleted along with the folder...? – Ashley Steel Oct 15 '13 at 22:01
  • 3
    @AshleySteel - Because when keeping the junctions, commands like takeown fail. Here's the error: INFO: The system cannot find the path specified. ( "C:\windows.old\Documents and Settings\All Users\Application Data\Application Data\Application Data\Application Data\Application Data\Application Data\Application Data\Application Data\Application Data\Application Data\Microsoft\Windows\SystemData\S-1-5-18\ReadOnly" ) ERROR: The filename, directory name, or volume label syntax is incorrect. - this looks like a recursion problem to me and it stops when the file path gets too long. – Peter Hahndorf Oct 16 '13 at 9:31
4

I used Peter H's answer and confirmed it does work, however I needed to do this on multiple servers, so I modified his code into a powershell script that can be executed either locally or via PS remoting from another machine. This is the .ps1 file:

# Script to remove windows.old after an upgrade

# Assumes path to sysinternals is in the PATH env variable


$ErrorActionPreference = "Inquire"

junction.exe -accepteula -s -q C:\windows.old | out-file $env:temp\juncts.txt -force

foreach ($line in [System.IO.File]::ReadLines("$env:temp\juncts.txt"))
 {
     if ($line -match "^\\\\")
     {
         $file = $line -replace "(: JUNCTION)|(: SYMBOLIC LINK)",""
         & junction.exe -d "$file"
     }
 }

 takeown /F C:\windows.old /R /D Y
 echo y | cacls C:\windows.old /T /G Everyone:F

 rm C:\windows.old -recurse -force
 rm "$env:temp\juncts.txt" -force
  • Yep this one works a treat. Don't forget to elevate powershell.exe privileges ("Run As Administrator") – Nexus Jun 25 '15 at 7:37
  • Line: echo y | cacls C:\windows.old /T /G Everyone:F Should be: echo y| cacls C:\windows.old /T /G Everyone:F No space between <kbd>y</kbd> and <kbd>|</kbd> – user437960 Oct 2 '17 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.