ExtractAll throws IOException

Nov 26, 2009 at 9:50 AM

Hi!

Thanks for a great lib.

I'm using it to backup and restore a folder structure used by a program of mine. Now, I've come across a problem in the extract process where I'm having a ZipException and an inner exception of IOException. I should mention also that this problem only happens when I'm overwriting existing files.

Here's the IOException:

Ionic.Zip.ZipException: Cannot extract ---> System.IO.IOException: The process cannot access the file 'C:\Temp\...\SomeFolder' because it is being used by another process.

at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Directory.OpenHandle(String path)
   at System.IO.Directory.SetCreationTimeUtc(String path, DateTime creationTimeUtc)
   at Ionic.Zip.ZipEntry._SetTimes(String fileOrDirectory, Boolean isFile)
   at Ionic.Zip.ZipEntry.InternalExtract(String baseDir, Stream outstream, String password)

The reason this fails is because I accidently had Explorer looking at the very same folder being extracted. I can understand this because Win explorer locks the folder it is viewing. So, I tried setting ZipFile.ExtractExistingFile = DoNotOverwrite thinking this would help, but it didn't.

Looking at the source code I can see that you're handling the _SetTimes(...) differently depending on whether its being called from InternalExtract() or from ValidateOutput(). In ValidateOutput() you would only call _SetTimes() for an existing folder if ExtractExistingFile equals OverwriteSilently.  

What I would like is to be able to overwrite any existing file but to leave existing folders untouched (due to the lock problem with Win Explorer). Is this possible?

Regards

/Calle

Nov 26, 2009 at 2:47 PM

Okey, so I almost got around the problem.

First of all I discovered that some directories in my zip files were not treated as separate ZipEntries. That's because I use ZipFile.AddEntry(string, string) and when adding files through this method (not directories) then the directory specified by directoryPathInArchive will not become a separate ZipEntry on extraction. During extraction when a ZipEntry represents a directory ValidateOutput() is called which honors the ZipEntry.ExtractExistingFile flag which is what I want.

Setting ZipFile.ExtractExistingFile = InvokeExtractProgressEvent and using the following ExtractProgress event handler code:

	if (e.CurrentEntry != null)
	{
		if (e.CurrentEntry.IsDirectory)
		{
			e.CurrentEntry.ExtractExistingFile = ExtractExistingFileAction.DoNotOverwrite;
		}
		else
		{
			e.CurrentEntry.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently;
		}
	}

gets me almost the whole way. Again turning to source code I see that after all files have extracted there is a separate loop that calls _SetTimes() for all directory zip-entries. Well, that's when my luck runs out. Trying to update the file time for the existing directory that win explorer is currently locking gives me the same IOException as before. So, what to do?

Regards

/Calle

Nov 30, 2009 at 8:58 AM

Ah, just found workitem #8807. I can confirm that 1.9 beta takes care of this (my) problem as well. Sorry for not searching harder... 

Best regards

/Calle