Compress-Archive Error: Cannot access the file because it is being used by another process

Viewed 12917

I would like to zip a path (with a service windows running inside).

When the service is stopped, it works perfectly, when the service is running, I have the exception:

The process cannot access the file because it is being used by another process.

However, when I zip with 7-zip, I don't have any exception.

My command:

Compress-Archive [PATH] -CompressionLevel Optimal -DestinationPath("[DEST_PATH]") -Force

Do you have any idea to perform the task without this exception?

3 Answers

Copy-Item allows you to access files that are being used in another process.

This is the solution I ended up using in my code:

Copy-Item -Path "C:\Temp\somefolder" -Force -PassThru | 
Get-ChildItem |
Compress-Archive -DestinationPath "C:\Temp\somefolder.zip"

The idea is that you pass through all the copied items through the pipeline instead of having to copy them to a specific destination first before compressing.

I like to zip up a folder's content rather than the folder itself, therefore I'm using Get-ChildItem before compressing in the last line.

Sub-folders are already included. No need to use -recurse in the first line to do this

A good method to access files being used by another process is by creating snapshots using Volume Shadow Copy Service.

To do so, one can simply use PowerShells WMI Cmdlets:

$Path = "C:/my/used/folder"
$directoryRoot = [System.IO.Directory]::GetDirectoryRoot($Path).ToString()

$shadow = (Get-WmiObject -List Win32_ShadowCopy).Create($directoryRoot, "ClientAccessible")
$shadowCopy = Get-WmiObject Win32_ShadowCopy | ? { $_.ID -eq $shadow.ShadowID }
$snapshotPath = $shadowCopy.DeviceObject + "\" + $Path.Replace($directoryRoot, "")

Now you can use the $snapshotPath as -Path for your Compress-Archive call.

This method can also be used to create backups with symlinks. From there on you can use the linked folders to copy backed up files, or to compress them without those Access exceptions.

I created a similiar function and a small Cmdlet in this Gist: Backup.ps1

There was a similar requirement where only few extensions needs to be added to zip. With this approach, we can copy the all files including locked ones to a temp location > Zip the files and then delete the logs

This is bit lengthy process but made my day!

$filedate = Get-Date -Format yyyyMddhhmmss
$zipfile = 'C:\Logs\logfiles'+ $filedate +'.zip'

New-Item -Path "c:\" -Name "Logs" -ItemType "directory" -ErrorAction SilentlyContinue

Robocopy "<Log Location>" "C:\CRLogs\" *.txt *.csv *.log /s
Get-ChildItem -Path "C:\Logs\" -Recurse | Compress-Archive -DestinationPath $zipfile -Force -ErrorAction Continue
Remove-Item -Path "C:\Logs\" -Exclude *.zip -Recurse -Force
Related