1

I have already tried something like:

While (Test-Path -Path $destinationApplicationFolder){
    Try{
        Remove-Item -Recurse -Force $destinationApplicationFolder -ErrorAction Stop
    }catch{
        IF((Test-Path -Path $destinationApplicationFolder) -eq $false) {
            Write-Warning "File or directory does not exist."       
        }
        Else {
            #Get-Process | foreach{$processVar = $_;$_.Modules | foreach{if($_.FileName -eq "$destinationApplicationFolder\CC.Core.POCO.dll"){$processVar.Name + " PID:" + $processVar.id}}}
            #Stop-Process $processVar -Force
            Get-Process | ?{$destinationApplicationFolder.path -and (test-path (split-path $destinationApplicationFolder.path -leaf ))} | Stop-Process -whatif
        }
    }
}

Is it possible to do this without installing other software?

  • You can't - same as you can't delete a file in Explorer that's currently open in other running processes. – auburg Feb 07 '20 at 17:05
  • @auburg: You can, if you are willing to kill (forcefully terminate) all processes that have handles to items in the directory subtree open, which is what Sergio is trying to do. – mklement0 Feb 07 '20 at 21:41

1 Answers1

1

To state what is perhaps obvious explicitly:

  • Forcefully terminating other processes with Stop-Process should generally be a last resort,

  • especially with the -Force switch, given that that will terminate other users' processes as well (should others be logged on to the same machine, possibly remotely), without warning - provided you're running in an elevated session (running as administrator), as only then do you have the necessary permissions.


If you're willing to assume this risk, and the assumption is that the only processes preventing your directory subtree from getting removed are those run from executables or DLLs located inside the target subtree, you can try:

while (Test-Path $destinationApplicationFolder) {

  try {
    Remove-Item -Recurse -Force $destinationApplicationFolder -ErrorAction Stop
  }
  catch {
    Get-Process | 
      Where-Object { $_.Modules.FileName -like "$destinationApplicationFolder\*" } |
        Stop-Process -ErrorAction Stop -WhatIf
  }

}

Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.

Note:

  • There may also be processes from executables located elsewhere that still block removal, if they have open handles to files and directories in the target directory subtree.

  • To also identify these, you have two options:

    • Use openfiles.exe /Query

      • openfiles.exe comes with Windows, but requires running openfiles /Local ON with elevation as a one-time setup action, after which a reboot is required.

      • Sample call:

        openfiles /query /FO csv | findstr.exe /L /c:$(Convert-Path someFile.txt)
        
    • Use the download-on-demand handle.exe SysInternals utility, which, once downloaded, requires no prior setup (add -nobanner (every time) to hide the copyright message; add -accepteula (at least once on a given machine) to accept the license).

      • Sample call:

        handle (Convert-Path someFile.docx)
        
  • Remove-Item -Recurse can generally fail in versions earlier than Windows 10 20H2 even if there are no processes blocking a directory's removal (and if there are no permission issues): Incredibly, the file/folder removal WinAPI functions are inherently asynchronous, which can cause intermittent, unpredictable failures - see this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775