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;
}
}