Skip to content

Commit 38b7690

Browse files
Copilotntrappe-msft
andcommitted
Improve windowsfilter directory removal with multiple fallback methods
Co-authored-by: ntrappe-msft <124631722+ntrappe-msft@users.noreply.github.com>
1 parent cdd2b8d commit 38b7690

1 file changed

Lines changed: 128 additions & 8 deletions

File tree

helpful_tools/Install-DockerCE/uninstall-docker-ce.ps1

Lines changed: 128 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,30 @@ Remove-DockerNetworks()
369369
}
370370
}
371371

372+
function
373+
Stop-WindowsContainerServices()
374+
{
375+
# Stop additional Windows Container services that might be locking files
376+
$services = @("cexecsvc", "vmcompute", "vmicguestinterface", "vmicheartbeat", "vmickvpexchange", "vmicrdv", "vmicshutdown", "vmictimesync", "vmicvmsession", "vmicvss")
377+
378+
foreach ($serviceName in $services)
379+
{
380+
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
381+
if ($service -and $service.Status -eq 'Running')
382+
{
383+
Write-Output "Stopping $serviceName service..."
384+
try
385+
{
386+
Stop-Service -Name $serviceName -Force -ErrorAction SilentlyContinue
387+
}
388+
catch
389+
{
390+
# Ignore errors for services we can't stop
391+
}
392+
}
393+
}
394+
}
395+
372396
function
373397
Remove-DockerData()
374398
{
@@ -377,8 +401,45 @@ Remove-DockerData()
377401
if (Test-Path $global:DockerDataPath)
378402
{
379403
Write-Output "Removing Docker data directory..."
404+
405+
# Stop additional services that might be locking container files
406+
Stop-WindowsContainerServices
407+
408+
# Wait a moment for services to fully stop
409+
Start-Sleep -Seconds 2
410+
380411
try
381412
{
413+
# Special handling for windowsfilter directory which is often problematic
414+
$windowsFilterPath = Join-Path $global:DockerDataPath "windowsfilter"
415+
if (Test-Path $windowsFilterPath)
416+
{
417+
Write-Output "Removing windowsfilter directory with special handling..."
418+
419+
# First, try to empty the windowsfilter directory using robocopy purge
420+
# This can sometimes handle locked files better than Remove-Item
421+
$tempEmptyDir = Join-Path $env:TEMP "EmptyDir_$(Get-Random)"
422+
New-Item -ItemType Directory -Path $tempEmptyDir -Force | Out-Null
423+
424+
try
425+
{
426+
# Use robocopy to mirror an empty directory (effectively purging)
427+
& robocopy.exe $tempEmptyDir $windowsFilterPath /MIR /R:1 /W:1 /NP /NFL /NDL /NJH /NJS 2>$null | Out-Null
428+
Remove-Item $tempEmptyDir -Force -ErrorAction SilentlyContinue
429+
}
430+
catch
431+
{
432+
# If robocopy fails, continue with other methods
433+
Remove-Item $tempEmptyDir -Force -ErrorAction SilentlyContinue
434+
}
435+
436+
# Try to remove using rd command which can handle some locked files
437+
if (Test-Path $windowsFilterPath)
438+
{
439+
& cmd.exe /c "rd /s /q `"$windowsFilterPath`"" 2>$null | Out-Null
440+
}
441+
}
442+
382443
# Take ownership of the Docker data directory and its contents
383444
# This is needed for directories like windowsfilter which have restrictive ACLs
384445
Write-Output "Taking ownership of Docker data directory..."
@@ -403,25 +464,84 @@ Remove-DockerData()
403464
{
404465
Write-Warning "Failed to terminate takeown process: $_"
405466
}
406-
Write-Error "Taking ownership of Docker data directory timed out after $timeoutMinutes minutes."
407-
return
467+
Write-Warning "Taking ownership of Docker data directory timed out after $timeoutMinutes minutes."
468+
# Continue with removal attempt even if takeown timed out
408469
}
409470

410471
# Grant full control to the current user
411472
& icacls.exe $global:DockerDataPath /grant "$env:USERNAME`:F" /t /c 2>$null | Out-Null
412473

413-
# Now attempt to remove the directory
414-
Remove-Item $global:DockerDataPath -Recurse -Force
474+
# Try multiple methods to remove the directory
475+
$removalSuccess = $false
476+
477+
# Method 1: PowerShell Remove-Item
478+
try
479+
{
480+
Remove-Item $global:DockerDataPath -Recurse -Force -ErrorAction Stop
481+
$removalSuccess = $true
482+
Write-Output "Docker data directory removed using Remove-Item."
483+
}
484+
catch
485+
{
486+
Write-Warning "Remove-Item failed: $_"
487+
}
488+
489+
# Method 2: If PowerShell failed, try rd command
490+
if (-not $removalSuccess -and (Test-Path $global:DockerDataPath))
491+
{
492+
try
493+
{
494+
& cmd.exe /c "rd /s /q `"$global:DockerDataPath`""
495+
if (-not (Test-Path $global:DockerDataPath))
496+
{
497+
$removalSuccess = $true
498+
Write-Output "Docker data directory removed using rd command."
499+
}
500+
}
501+
catch
502+
{
503+
Write-Warning "rd command failed: $_"
504+
}
505+
}
506+
507+
# Method 3: If still exists, try robocopy purge on the entire directory
508+
if (-not $removalSuccess -and (Test-Path $global:DockerDataPath))
509+
{
510+
try
511+
{
512+
$tempEmptyDir = Join-Path $env:TEMP "EmptyDir_$(Get-Random)"
513+
New-Item -ItemType Directory -Path $tempEmptyDir -Force | Out-Null
514+
515+
# Use robocopy to mirror an empty directory over the Docker data directory
516+
& robocopy.exe $tempEmptyDir $global:DockerDataPath /MIR /R:1 /W:1 /NP /NFL /NDL /NJH /NJS 2>$null | Out-Null
517+
518+
# Then remove the now-empty directory
519+
Remove-Item $global:DockerDataPath -Force -ErrorAction SilentlyContinue
520+
Remove-Item $tempEmptyDir -Force -ErrorAction SilentlyContinue
521+
522+
if (-not (Test-Path $global:DockerDataPath))
523+
{
524+
$removalSuccess = $true
525+
Write-Output "Docker data directory removed using robocopy purge."
526+
}
527+
}
528+
catch
529+
{
530+
Write-Warning "robocopy purge failed: $_"
531+
Remove-Item $tempEmptyDir -Force -ErrorAction SilentlyContinue
532+
}
533+
}
415534

416-
# Sanity check: Verify the Docker folder no longer exists
535+
# Final sanity check: Verify the Docker folder no longer exists
417536
if (Test-Path $global:DockerDataPath)
418537
{
419-
Write-Warning "Docker data directory still exists after removal attempt: $global:DockerDataPath"
420-
Write-Warning "You may need to manually remove $global:DockerDataPath"
538+
Write-Warning "Docker data directory still exists after all removal attempts: $global:DockerDataPath"
539+
Write-Warning "The windowsfilter subdirectory may still be in use by Windows Container services."
540+
Write-Warning "You may need to restart your system and manually remove $global:DockerDataPath"
421541
}
422542
else
423543
{
424-
Write-Output "Docker data directory removed."
544+
Write-Output "Docker data directory successfully removed."
425545
}
426546
}
427547
catch

0 commit comments

Comments
 (0)