I am downloading a large ZIP file, unzipping and then deleting that Zip to save space. Or at least trying. Some non trivial number of times, the delete that follows the unzip produces
System.Management.Automation.MethodInvocationException
Exception calling "Delete" with "1" argument(s): "The process cannot access the file 'C:\Users\Px_Install\AppData\Local\Temp\Revit_2023.zip' because it is being used by another process."
On thing I have used before for similar situations is to retry the delete over and over, with a couple second delay between tries, and a total number of retries before giving up. But that's pretty ugly. Especially because the exception type for the delete is pretty generic, so I can't really catch
on JUST this condition.
I am using
[IO.Compression.ZipFile]::ExtractToDirectory($downloadFilePath, $deploymentPath)
to do the unzip, and I wonder if there is anything I can do here to ensure that the file lock on the zip file is released immediately? Also, being an issue that comes up in other situations, I wonder if there is a more generic approach that allows me to force the file lock to be addressed immediately on a file by file basis? Failing that, there doesn't seem to be anything I can .Dispose
, so maybe there is a different approach that doesn't use a static method, which then provides a way to .Dispose
?
EDIT: I am now trying to just identify what is holding the lock, per @santiago-squarzon 's comment about AV. I can create a file that is locked, in the sense that I can't delete it, with this
#$path = '\\Mac\iCloud Drive\Px Tools\PS Concepts\FileLock and delete\New Text Document.txt'
$path = 'C:\\New Text Document.txt'
$stream = [System.IO.StreamWriter]::new($Path)
$stream.close()
if $stream.close()
is remmed out. As such, I modified the code here to just find the process that has the lock. No delete and certainly no stop process, since that process, in theory should be the ISE where I am testing the code. So this
foreach ($process in Get-Process) {
if ($lockingProcess = ($process.Modules | where {$_.FileName -eq $path})) {
break
}
}
Write-Host "$($lockingProcess.Count)"
Write-Host "$($lockingProcess.Name)"
just before the Close. Nothing. I also tried
if ($lockingProcess = ($process.Modules | where {$_.FileName -contains $path})) {
break
}
because that makes more logical sense to me, even though the linked code uses -eq
which may well work through some PowerShell magic. Still nothing so then I tried
foreach ($process in Get-Process) {
Write-Host "$($process.Name)"
foreach ($filename in $process.Modules.FileName) {
Write-Host " $filename"
}
}
to just get a list of every file being used/locked by each process. Lots of files listed, but never the target file. So now I wonder
1: Is that linked code even viable? And
2: AM I really understanding what a locked file is?