1

I'm having some issues with the Shell32 CopyHere method.

First of all, I'm working from this page: http://www.codeproject.com/Tips/257193/Easily-zip-unzip-files-using-Windows-Shell32

I was hoping to rewrite something similar in C# just because I hardly ever work in VB.NET.

I'm passing an input directory i that has one text file in it as my test. At the bottom, just so I see that it's in fact grabbing my files, I write the count of input.Items() and I get 1, so I think it's seeing my directory with the one text file in it. However, while my code creates the empty zip file just fine, and at least from that console output appears to be grabbing my files, it doesn't actually copy anything into the zip file. No errors are thrown, it's just as if nothing happens.

static void Zip(string i, string o)
{
        //Turn relative paths into full paths for Shell.NameSpace method.
        string ifp = Path.GetFullPath(i);
        string ofp = Path.GetFullPath(o);

        //Validate parameters.
        if (!(Directory.Exists(ifp)) || (Directory.GetFiles(ifp).Count() <= 0))
            throw new Exception("Input directory " + i + " was invalid.  " + i + " was either empty or doesn't exist.");
        string ext = ofp.Substring(ofp.Length - 4, 4);
        if (ext != ".zip")
            throw new Exception("Output zip directory " + o + " was invalid.  File extension was " + ext + " when it should be .zip.");
        if (File.Exists(ofp))
            throw new Exception("Output zip directory " + o + " was invalid.  Zip file already exists.");

        //The following data represents an empty zip file.
        byte[] startBuffer = { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        //Create empty zip file.
        File.WriteAllBytes(ofp, startBuffer);
        if (!File.Exists(ofp))
            throw new Exception("Output zip directory " + o + " was unable to be created.");

        Shell sc = new Shell();
        //Folder which contains the files you want to zip.
        Folder input = sc.NameSpace(ifp);
        //Empty zip file as folder.
        Folder output = sc.NameSpace(ofp);
        //Copy the files into the empty zip file.
        output.CopyHere(input.Items(), 4);
        Console.WriteLine(input.Items().Count);
}

Is there something wrong with how I'm using the Shell32 methods?

EDIT:

Sorry for the slow response, I'm trying to work with some of the code DJ Kraze put up.

To clarify some things, unfortunately I can't use a third party tool and I'm on .NET 4.0. I'm going to try taking DJ's advice and see if I can get either the VB version working or the C# that he kindly posted.

Thanks for the help everyone.

Mike
  • 399
  • 2
  • 9
  • 19
  • have you debugged the code..? also have you tested the code that was there in VB to see if it works and what results it yields..? – MethodMan May 23 '14 at 16:51
  • I will post the C# equiv of the code from that VB project below – MethodMan May 23 '14 at 16:52
  • Mike, please add sentence about why you are doing it - if "work with Zip files" than it is duplicate of http://stackoverflow.com/questions/940582/how-do-i-zip-a-file-in-c-using-no-3rd-party-apis. – Alexei Levenkov May 23 '14 at 17:00

4 Answers4

5

the code here will be the C# equivalent to the VB.NET code from the codeproject page

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class Form1
{

    public void Zip()
    {
        //1) Lets create an empty Zip File .
        //The following data represents an empty zip file .

        byte[] startBuffer = {
            80,
            75,
            5,
            6,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0,
            0
        };
        // Data for an empty zip file .
        FileIO.FileSystem.WriteAllBytes("d:\\empty.zip", startBuffer, false);

        //We have successfully made the empty zip file .

        //2) Use the Shell32 to zip your files .
        // Declare new shell class
        Shell32.Shell sc = new Shell32.Shell();
        //Declare the folder which contains the files you want to zip .
        Shell32.Folder input = sc.NameSpace("D:\\neededFiles");
        //Declare  your created empty zip file as folder  .
        Shell32.Folder output = sc.NameSpace("D:\\empty.zip");
        //Copy the files into the empty zip file using the CopyHere command .
        output.CopyHere(input.Items, 4);

    }

    public void UnZip()
    {
        Shell32.Shell sc = new Shell32.Shell();
        //'UPDATE !!
        //Create directory in which you will unzip your files .
        IO.Directory.CreateDirectory("D:\\extractedFiles");
        //Declare the folder where the files will be extracted
        Shell32.Folder output = sc.NameSpace("D:\\extractedFiles");
        //Declare your input zip file as folder  .
        Shell32.Folder input = sc.NameSpace("d:\\myzip.zip");
        //Extract the files from the zip file using the CopyHere command .
        output.CopyHere(input.Items, 4);

    }

}
MethodMan
  • 18,625
  • 6
  • 34
  • 52
  • +1. Consider editing code to have `startBuffer` in one row and possible adding comment about using existing .Net libraries to deal with Zip files instead of manual interop. – Alexei Levenkov May 23 '14 at 16:57
  • I agree Alexei, I was just doing a quick conversion for him so that he could see what the VB code looks like in C# also feel free to edit my example as you please since it was only posted as an example for the OP to use / debug.. – MethodMan May 23 '14 at 17:00
  • 1
    So when I take out the variable file paths, and type them directly into the NameSpace calls and the WriteAllByte call as you have done, everything works perfectly. I'm not sure why, but at least I should be able to figure it out from there. Thanks for your help! – Mike May 23 '14 at 19:14
1

Based off Simon McKenzie's answer to this question, I'd suggest using a pair of methods like this:

    public static void ZipFolder(string sourceFolder, string zipFile)
    {
        if (!System.IO.Directory.Exists(sourceFolder))
            throw new ArgumentException("sourceDirectory");

        byte[] zipHeader = new byte[] { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

        using (System.IO.FileStream fs = System.IO.File.Create(zipFile))
        {
            fs.Write(zipHeader, 0, zipHeader.Length);
        }

        dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
        dynamic source = shellApplication.NameSpace(sourceFolder);
        dynamic destination = shellApplication.NameSpace(zipFile);

        destination.CopyHere(source.Items(), 20);
    }

    public static void UnzipFile(string zipFile, string targetFolder)
    {
        if (!System.IO.Directory.Exists(targetFolder))
            System.IO.Directory.CreateDirectory(targetFolder);

        dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
        dynamic compressedFolderContents = shellApplication.NameSpace(zipFile).Items;
        dynamic destinationFolder = shellApplication.NameSpace(targetFolder);

        destinationFolder.CopyHere(compressedFolderContents);
    }
}
Community
  • 1
  • 1
mccdyl001
  • 182
  • 11
0

If you're using .NET 4.5, there's System.IO.Compression.ZipFile. That should be much easier - and better tested that what you're using.

David Crowell
  • 3,711
  • 21
  • 28
0

Why are you rolling your own zip tool?

Just use DotNetZip. Free, fast, simple. See

Creating a zip archive can be as simple as

using (ZipFile zip = new ZipFile())
 {

   // add this map file into the "images" directory in the zip archive
   zip.AddFile( @"c:\images\personal\7440-N49th.png", "images");

   // add the report into a different directory in the archive
   zip.AddFile( "c:\Reports\2008-Regional-Sales-Report.pdf" , "files" ) ;

   zip.AddFile( "ReadMe.txt");

   zip.Save("c:MyZipFile.zip");
 }

Unzipping is about the same level of complexity.

Community
  • 1
  • 1
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135