Thursday, November 23, 2017

Delete the undeletable on Windows

I had trouble deleting C:\ProgramData\Docker on Docker for Windows using Windows containers. This is because it contains a full Windows directory layout, with all system files and special permissions and flags. Here's a Powershell snippet to get a file hierarchy on Windows into a state where it can be deleted.

$ErrorActionPreference = "stop"

function reallyDelete($d) {
    function renameToNumbersRecursive($dir) {
        $i = 0
        foreach($f in (dir $dir)) {
            while(Test-Path ($dir + "\" + $i)) {
                $i++
            }
            try {
                Rename-Item $f.FullName ($dir + "\" + $i)
            } catch {
                takeown /f $dir | Out-Null
                icacls $dir /reset | Out-Null
                takeown /f $f.FullName | Out-Null
                icacls $f.FullName /reset | Out-Null
                Rename-Item $f.FullName ($dir + "\" + $i)
            }
        }

        foreach($f in (dir $dir)) {
            if($f -is [System.IO.DirectoryInfo]) {
                renameToNumbersRecursive($f.FullName)
            }
        }
    }

    # paths might become too long for icacls, so rename paths to short numbers
    renameToNumbersRecursive $d

    takeown /f $d /r   | Out-Null
    icacls $d /reset /T   | Out-Null

    attrib -s -h -r "$d\*.*" /s /d   | Out-Null

    cmd /c del /s /q $d   | Out-Null
    cmd /c rmdir /s /q $d   | Out-Null
}

reallyDelete "C:\ProgramData\Docker"