Hyzac Hyzac - 12 days ago 8
C# Question

SharpCompress unpacking locks files

Im trying to make a process where I unpack a set of rar-files using SharpCompress and then delete them.

I first have a foreach loop which loops over the different set of files to be unpacked like this:

foreach (var package in extractionPackages.Where(package => Extractor.ExtractToFolder(package, destinationFolder)))
{
FileHelper.DeleteExtractionFiles(package);
}


The extraction process is taken straight of the SharpCompress Tests code and goes like this:

public static bool ExtractToFolder(ExtractionPackage extractionPackage, string extractionPath)
{
var fullExtractionPath = Path.Combine(extractionPath, extractionPackage.FolderName);
try
{
using (var reader = RarReader.Open(extractionPackage.ExtractionFiles.Select(p => File.OpenRead(p.FullPath))))
{
while (reader.MoveToNextEntry())
{
reader.WriteEntryToDirectory(fullExtractionPath, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
}

}

return true;
}
catch (Exception)
{
return false;
}
}


As you can see in the first code block I then call to delete the files but there I recieve an error due to that the files are locked by another process:
The process cannot access the file 'file.rar' because it is being used by another process.

If I try to put the deletion after the foreach-loop I am able to delete all but the last set of files if there are more than one. If it is just one the same issue occurs since the last set of files doesn't seems to be "unlocked".

How can I structure the code so that the files is unlocked?

Answer

By using an example from Nunrar and modifying it a bit I finally seems to have solved the issue:

public static bool ExtractToFolder(ExtractionPackage extractionPackage, string extractionPath)
    {
        var fullExtractionPath = Path.Combine(extractionPath, extractionPackage.FolderName);

        try
        {
            using (var reader = RarReader.Open(GetStreams(extractionPackage)))//extractionPackage.ExtractionFiles.Select(p => File.OpenRead(p.FullPath)), Options.None))
            {
                while (reader.MoveToNextEntry())
                {
                    reader.WriteEntryToDirectory(fullExtractionPath, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite);
                }
            }

            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

    private static IEnumerable<Stream> GetStreams(ExtractionPackage package)
    {
        foreach (var item in package.ExtractionFiles)
        {
            using (Stream input = File.OpenRead(item.FullPath))
            {
                yield return input;
            }
        }
    }