Building a New Mouse Trap II : Unzip

Saturday, November 26, 2005

In 1.1 we needed third party libraries to compress and uncompress data. In .NET 2.0 we have GZipStream and DeflateStream classes. However, as Stephen Toub points out in .NET matters, these classes are don’t handle the headers, footers, and other metadata of popular archive formats like gzip and zip.

In looking for the simplest possible solution to unzipping a single file in a windows forms application, I decided to interop with Shell32.dll. The disadvantage appears to be the inability to perform a “silent” operation – the shell always displays a modeless progress dialog no matter what flags are passed to the CopyHere method.  I tried to do some native interop debugging to figure out if the flags parameters was somehow getting munged in the interop boundary, but gave up. Part of my frustration was the disappearance of the Registers and Modules windows in the Visual Studio menus. I had to look up the shortcut keys to get to these commands. Apparently, this is a “feature” of the 2005 IDE that Paul Litwin also ran into.

The advantage to using Shell32 is the small amount of code required.

public class UnzipLogFileTransformer : ITransformer

{

    public string TransformFile(string inputFileName)

    {

        Check.IsRootedFileName(inputFileName, "inputFileName");      

        string destinationPath = Path.GetDirectoryName(inputFileName);

 

        string outputFileName = Unzip(inputFileName, destinationPath);

        File.Delete(inputFileName);

 

        return Path.Combine(destinationPath, outputFileName);

    }

 

    private string Unzip(string inputFileName, string destinationPath)

    {

        Shell shell = new ShellClass();

        Folder sourceFolder = shell.NameSpace(inputFileName);

        Folder destinationFolder = shell.NameSpace(destinationPath);

 

        Check.IsTrue(sourceFolder.Items().Count == 1,

            "Archive should contain only 1 item");

 

        string outputFileName = sourceFolder.Items().Item(0).Name;

        Check.IsNotNullOrEmpty(outputFileName, "outputFileName");

 

        destinationFolder.CopyHere(sourceFolder.Items(),

                                    OpFlags.TotallySilent);

 

        return outputFileName;

    }

}


Comments
matt Wednesday, March 8, 2006
YOU are a beautiful man. Thank you for this. I have been trying to put a square in a round hole for a week now (using gzipstream and deflatestream for a winzipped file). For the onlookers, here it is in vb.net.

Public Class clsZIP
Public Sub unzip(ByVal sourceFile As String)
Dim myShell As New Shell32.Shell
Dim sourceFolder As Shell32.Folder = myShell.NameSpace(sourceFile)
Dim destinationFolder As Shell32.Folder = myShell.NameSpace(sourceFolder.ParentFolder)
Dim outputFilename As String = sourceFolder.Items().Item(0).Name
destinationFolder.CopyHere(sourceFolder.Items())
MsgBox(outputFilename)
End Sub
End Class

Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!