@@ -108,15 +108,27 @@ Stop-Docker()
108108{
109109 if (Test-Docker )
110110 {
111- Write-Output " Stopping Docker service... "
112- try
111+ $service = Get-Service - Name $ global :DockerServiceName - ErrorAction SilentlyContinue
112+ if ( $service .Status -eq ' Running ' )
113113 {
114- Stop-Service - Name $global :DockerServiceName - Force - ErrorAction Stop
115- Write-Output " Docker service stopped successfully."
114+ Write-Output " Stopping Docker service..."
115+ try
116+ {
117+ Stop-Service - Name $global :DockerServiceName - Force - ErrorAction Stop
118+ Write-Output " Docker service stopped successfully."
119+ }
120+ catch
121+ {
122+ Write-Warning " Failed to stop Docker service: $_ "
123+ }
116124 }
117- catch
125+ elseif ($service.Status -eq ' Stopped' )
126+ {
127+ Write-Output " Docker service is already stopped."
128+ }
129+ else
118130 {
119- Write-Warning " Failed to stop Docker service: $_ "
131+ Write-Output " Docker service is in ' $ ( $ service.Status ) ' state. "
120132 }
121133 }
122134 else
@@ -201,17 +213,113 @@ Remove-DockerBinaries()
201213 }
202214}
203215
216+ function
217+ Remove-DockerContainers ()
218+ {
219+ Write-Output " Checking for existing Docker containers..."
220+ try
221+ {
222+ $containers = docker ps - aq 2> $null
223+ if ($containers )
224+ {
225+ $containerCount = ($containers | Measure-Object ).Count
226+ $runningContainers = docker ps - q 2> $null
227+ $runningCount = if ($runningContainers ) { ($runningContainers | Measure-Object ).Count } else { 0 }
228+
229+ Write-Output " Found $containerCount Docker container(s) ($runningCount running)."
230+
231+ if (-not $Force )
232+ {
233+ $message = " Do you want to stop and remove all $containerCount Docker container(s)"
234+ if ($runningCount -gt 0 ) { $message += " (including $runningCount running)" }
235+ $message += " ? (y/N)"
236+
237+ $response = Read-Host $message
238+ if ($response -ne " y" -and $response -ne " Y" )
239+ {
240+ Write-Output " Skipping Docker containers removal."
241+ return
242+ }
243+ }
244+
245+ Write-Output " Stopping and removing all Docker containers..."
246+ docker stop $containers 2> $null | Out-Null
247+ docker rm -f $containers 2> $null
248+ Write-Output " Docker containers removed."
249+ }
250+ else
251+ {
252+ Write-Output " No Docker containers found."
253+ }
254+ }
255+ catch
256+ {
257+ Write-Warning " Failed to remove Docker containers: $_ "
258+ }
259+ }
260+
261+ function
262+ Remove-DockerVolumes ()
263+ {
264+ Write-Output " Checking for existing Docker volumes..."
265+ try
266+ {
267+ $volumes = docker volume ls - q 2> $null
268+ if ($volumes )
269+ {
270+ $volumeCount = ($volumes | Measure-Object ).Count
271+ Write-Output " Found $volumeCount Docker volume(s)."
272+
273+ if (-not $Force )
274+ {
275+ $response = Read-Host " Do you want to remove all $volumeCount Docker volume(s)? (y/N)"
276+ if ($response -ne " y" -and $response -ne " Y" )
277+ {
278+ Write-Output " Skipping Docker volumes removal."
279+ return
280+ }
281+ }
282+
283+ Write-Output " Removing all Docker volumes..."
284+ docker volume rm -f $volumes 2> $null
285+ Write-Output " Docker volumes removed."
286+ }
287+ else
288+ {
289+ Write-Output " No Docker volumes found."
290+ }
291+ }
292+ catch
293+ {
294+ Write-Warning " Failed to remove Docker volumes: $_ "
295+ }
296+ }
297+
204298function
205299Remove-DockerImages ()
206300{
207301 if ($RemoveImages )
208302 {
209- Write-Output " Removing all Docker images..."
303+ Write-Output " Checking for existing Docker images..."
210304 try
211305 {
212306 $images = docker images - q 2> $null
213307 if ($images )
214308 {
309+ $imageCount = ($images | Measure-Object ).Count
310+ Write-Output " Found $imageCount Docker image(s)."
311+
312+ if (-not $Force )
313+ {
314+ $response = Read-Host " Do you want to remove all $imageCount Docker image(s)? (y/N)"
315+ if ($response -ne " y" -and $response -ne " Y" )
316+ {
317+ Write-Output " Skipping Docker images removal."
318+ return
319+ }
320+ }
321+
322+ Write-Output " Removing all Docker images..."
215323 docker rmi -f $images 2> $null
216324 Write-Output " Docker images removed."
217325 }
@@ -274,7 +382,30 @@ Remove-DockerData()
274382 # Take ownership of the Docker data directory and its contents
275383 # This is needed for directories like windowsfilter which have restrictive ACLs
276384 Write-Output " Taking ownership of Docker data directory..."
277- & takeown.exe / f $global :DockerDataPath / r / d y 2> $null | Out-Null
385+
386+ # Use Start-Process with timeout to handle hanging takeown operation
387+ $takeownProcess = Start-Process - FilePath " takeown.exe" - ArgumentList " /f" , $global :DockerDataPath , " /r" , " /d" , " y" - WindowStyle Hidden - PassThru - RedirectStandardOutput $null - RedirectStandardError $null
388+
389+ # Wait for up to 3 minutes for takeown to complete
390+ $timeoutMinutes = 3
391+ $timeoutMs = $timeoutMinutes * 60 * 1000
392+
393+ if (-not $takeownProcess.WaitForExit ($timeoutMs ))
394+ {
395+ # Process is still running after timeout, kill it
396+ Write-Warning " Taking ownership is taking longer than $timeoutMinutes minutes. Terminating process..."
397+ try
398+ {
399+ $takeownProcess.Kill ()
400+ $takeownProcess.WaitForExit (5000 ) # Wait up to 5 seconds for kill to complete
401+ }
402+ catch
403+ {
404+ Write-Warning " Failed to terminate takeown process: $_ "
405+ }
406+ Write-Error " Taking ownership of Docker data directory timed out after $timeoutMinutes minutes."
407+ return
408+ }
278409
279410 # Grant full control to the current user
280411 & icacls.exe $global :DockerDataPath / grant " $env: USERNAME `:F" / t / c 2> $null | Out-Null
@@ -317,8 +448,36 @@ Remove-DockerData()
317448}
318449
319450function
320- Remove-WindowsFeatures ()
451+ Remove-DockerRegistryKeys ()
321452{
453+ Write-Output " Removing Docker registry keys..."
454+
455+ $registryPaths = @ (
456+ " HKLM:\SYSTEM\CurrentControlSet\Services\docker" ,
457+ " HKLM:\SYSTEM\ControlSet002\Services\docker"
458+ )
459+
460+ foreach ($regPath in $registryPaths )
461+ {
462+ try
463+ {
464+ if (Test-Path $regPath )
465+ {
466+ Write-Output " Removing registry key: $regPath "
467+ Remove-Item $regPath - Recurse - Force
468+ Write-Output " Registry key removed: $regPath "
469+ }
470+ else
471+ {
472+ Write-Output " Registry key not found: $regPath "
473+ }
474+ }
475+ catch
476+ {
477+ Write-Warning " Failed to remove registry key $regPath `: $_ "
478+ }
479+ }
480+ }
322481 if ($RemoveWindowsFeatures )
323482 {
324483 Write-Output " WARNING: Removing Windows features may affect other software on this system."
@@ -419,16 +578,42 @@ Remove-DockerCE()
419578 }
420579 }
421580
422- # Remove images and networks first (while Docker is still running)
581+ # Remove containers, volumes, images and networks first (while Docker is still running or available)
582+ # We'll try to clean these up even if the service is stopped, as docker CLI might still work
423583 if (Test-Docker )
424584 {
425- Remove-DockerImages
426- Remove-DockerNetworks
585+ try
586+ {
587+ # Test if docker CLI is available and responsive
588+ $null = docker version 2> $null
589+ if ($LASTEXITCODE -eq 0 )
590+ {
591+ Remove-DockerContainers
592+ Remove-DockerVolumes
593+ Remove-DockerImages
594+ Remove-DockerNetworks
595+ }
596+ else
597+ {
598+ Write-Output " Docker CLI is not responsive. Skipping container/volume/image/network cleanup."
599+ }
600+ }
601+ catch
602+ {
603+ Write-Output " Docker CLI is not available. Skipping container/volume/image/network cleanup."
604+ }
605+ }
606+ else
607+ {
608+ Write-Output " Docker service not found. Skipping container/volume/image/network cleanup."
427609 }
428610
429611 # Stop and remove Docker service
430612 Remove-DockerService
431613
614+ # Remove Docker registry keys
615+ Remove-DockerRegistryKeys
616+
432617 # Remove binaries
433618 Remove-DockerBinaries
434619
0 commit comments