Getting a list of files from a ZipPackage

In my current project I needed to get a list of files that were in a zip file. In the past when I needed to do this I would have used J# and just added a reference. Since J# is not included I wanted to see if there was a different way to achieve this.

Microsoft has since added a System.IO.Packaging namespace that includes the ZipPackage class. I added a reference to WindowsBase.dll because that is where the ZipPackage class is.

As I researched about using the class I found that it does not provide a public method to get a list of the files. As I looked at the data I noticed a field named _zipArchive of the type MS.Internal.IO.Zip.ZipArchive. I looked further in the field and noticed a property named ZipFileInfoDictionary which is a System.Collections.Hashtable.

By using reflection I was able to access the _zipArchive and the ZipFileInfoDictionary to retrieve the file list.

I have created the following extension method called GetFileList to return the list of files in the zip file.

public static List<string> GetFileList(this ZipPackage zp)
{
    List<string> list = null;
 
    try
    {
        var zipArchiveProperty = zp.GetType().GetField("_zipArchive", 
                                    BindingFlags.Static 
                                    | BindingFlags.NonPublic 
                                    | BindingFlags.Instance);
 
        var zipArchive = zipArchiveProperty.GetValue(zp);
 
        var zipFileInfoDictionaryProperty = 
            zipArchive.GetType().GetProperty("ZipFileInfoDictionary", 
                                            BindingFlags.Static 
                                            | BindingFlags.NonPublic 
                                            | BindingFlags.Instance);
 
        var zipFileInfoDictionary = 
            zipFileInfoDictionaryProperty.GetValue(zipArchive, null) as Hashtable;
 
        var query = from System.Collections.DictionaryEntry de in zipFileInfoDictionary
                    select de.Key.ToString();
 
        list = query.ToList();
    }
    catch (NotSupportedException nse)
    {
        throw;
    }
    return list;
}

To call the method I used the following:

private List<string> GetFileListFromZipFile(FileInfo zipFileName)
{
    List<string> list = null;
 
    try
    {
        var zp = ZipPackage.Open(zipFileName.FullName, 
                                 FileMode.Open, 
                                 FileAccess.Read, 
                                 FileShare.Read) as ZipPackage;
        list = zp.GetFileList();
    }
    catch (NotSupportedException nse)
    {
        throw;
    }
    return list;
}

I ended up having to use the FileShare.Read because I was getting a file in use exception.

Comments are closed.