The stream that is internally created by the CreateFromDirectory method remains opened and the user can't close it:
This is error message observed when using the below code snippet:
The process cannot access the file 'C:\Users\dyordano\OneDrive - Progress Software Corporation\MyProjects\1640071ZipFileCreateFromDirectory\myzip.zip' because it is being used by another process.
static void Main(string[] args)
{
string archiveFileName = @"..\..\myzip.zip";
string sourceDirectoryName = @"..\..\Folder";
File.Delete(archiveFileName);
Telerik.Windows.Zip.Extensions.ZipFile.CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);
using (Stream stream = File.Open(archiveFileName, FileMode.Open))
{
}
}
Workaround:
static void Main(string[] args)
{
string archiveFileName = @"..\..\myzip.zip";
string sourceDirectoryName = @"..\..\Folder";
File.Delete(archiveFileName);
// Telerik.Windows.Zip.Extensions.ZipFile.CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);
CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);
using (Stream stream = File.Open(archiveFileName, FileMode.Open))
{
}
}
private static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName, Telerik.Windows.Zip.CompressionLevel compressionLevel, bool includeBaseDirectory)
{
Encoding entryNameEncoding = null;
DeflateSettings compressionSettings = new DeflateSettings()
{
CompressionLevel = compressionLevel,
HeaderType = CompressedStreamHeader.None
};
char[] directorySeparatorChar = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
sourceDirectoryName = Path.GetFullPath(sourceDirectoryName);
destinationArchiveFileName = Path.GetFullPath(destinationArchiveFileName);
FileStream fileStream = File.Open(destinationArchiveFileName, FileMode.CreateNew, FileAccess.Write, FileShare.None); ;
using (ZipArchive zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Create,false, entryNameEncoding))
{
bool empty = true;
DirectoryInfo directoryInfo = new DirectoryInfo(sourceDirectoryName);
string fullName = directoryInfo.FullName;
if (includeBaseDirectory && directoryInfo.Parent != null)
{
fullName = directoryInfo.Parent.FullName;
}
foreach (FileSystemInfo fileSystemInfo in directoryInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories))
{
empty = false;
int length = fileSystemInfo.FullName.Length - fullName.Length;
string entryName = fileSystemInfo.FullName.Substring(fullName.Length, length);
entryName = entryName.TrimStart(directorySeparatorChar);
DirectoryInfo subfolder = fileSystemInfo as DirectoryInfo;
if (subfolder != null)
{
if (IsDirectoryEmpty(subfolder))
{
zipArchive.CreateEntry(string.Concat(entryName, Path.DirectorySeparatorChar));
}
}
else
{
ZipFile.CreateEntryFromFile(zipArchive, fileSystemInfo.FullName, entryName, compressionSettings);
}
}
if (includeBaseDirectory && empty)
{
zipArchive.CreateEntry(string.Concat(directoryInfo.Name, Path.DirectorySeparatorChar));
}
}
}
private static bool IsDirectoryEmpty(DirectoryInfo directoryInfo)
{
bool empty = true;
using (IEnumerator<FileSystemInfo> enumerator = directoryInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories).GetEnumerator())
{
if (enumerator.MoveNext())
{
empty = false;
}
}
return empty;
}
Note: We should ensure that all of the obsolete API that used to use the "leave open" flag don't keep the stream locked.