Embedding the DotNetZip DLL

Mar 20, 2010 at 9:05 AM

hi,

 

i have a little problem with the embedding in c# (c#newbie)

 

my code..

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace Test
{ class WebifyChmForm { static WebifyChmForm() { AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver); } static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args) { Assembly a1 = Assembly.GetExecutingAssembly(); Stream s = a1.GetManifestResourceStream("Ionic.Zip.dll"); byte[] block = new byte[s.Length]; s.Read(block, 0, block.Length); Assembly a2 = Assembly.Load(block); return a2; } } }

code in form1 from button


 private void button1_Click(object sender, EventArgs e)
        {


            using (ZipFile zip = new ZipFile())
            {
                
                zip.AddFile("test.png");
                zip.AddFile("test1.png");
                zip.Save("myzip.zip");
            }

        }


here comes a error (bold)

using (ZipFile zip = new ZipFile())

error: The type or namespace name "ZipFile" could not be found. (Missing a using directive or an assembly reference?)

why not this work?


sorry for my bad english..
Coordinator
Mar 23, 2010 at 4:50 PM

How did you embed the DotNetZip assembly into your EXE?

Depending on how you did that, the name of the embedded stream will vary.  It could have the name of your Visual studio project in it:  MyProject1.Ionic.Zip.dll . Or it might not.

You can check the names of resources in your assembly by using this kind of code:

        public void Run()
        {
            var tAssembly = Assembly.LoadFrom(_assemblyName);

            string[] resourceNames = tAssembly.GetManifestResourceNames();
            if (resourceNames != null && resourceNames.Length > 0)
            {

                foreach(string resourceName in resourceNames)
                {
                    System.Console.WriteLine(resourceName);
                }
            }
            else
            {
                System.Console.WriteLine("-none-");
            }
        }

I've written a simple tool that can do this for you, for any .NET assembly. It's available for download.

it looks like this:

Oct 2, 2010 at 2:58 PM
Edited Oct 2, 2010 at 9:40 PM

Hi ! I have the same problem. When I run your software, I see :  "MyProject.Ionic.Zip.dll" !  But I do not know how to compile my project without this error:

error: The  type or namespace name "ZipFile" could not be found. (Missing a  using directive or an assembly reference?)

I have a warning message :
Unable to apply the advertisement properties for the element "ionic.zip.dll.MyProject"

Could you please make a small project (console or window) to compress a file using the included DLL file ?

Thanking you in anticipation !

 

It's an example of my project :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
//using Ionic.Zip;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {

        // static constructor to add a handler to the AssemblyResolve event 
        static Program()  //   <--- this must be the name of your main class
        {
            AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(Resolver);
        }

        static System.Reflection.Assembly Resolver(object sender, ResolveEventArgs args)
        {
            Assembly a1 = Assembly.GetExecutingAssembly();
            System.IO.Stream s = a1.GetManifestResourceStream("Ionic.Zip.dll");
            byte[] block = new byte[s.Length];
            s.Read(block, 0, block.Length);
            Assembly a2 = Assembly.Load(block);
            return a2;
        }


        static void Main(string[] args)
        {
            System.Console.WriteLine("Compressing ...");
  using (ZipFile zip = new ZipFile()) { zip.AddFile("image.png"); zip.Save("image_compressed.zip"); } System.Console.Write("End !"); System.Console.ReadLine(); }
  } }

Help me please !

Coordinator
Oct 5, 2010 at 12:10 PM
Edited Oct 6, 2010 at 1:37 PM
No, I don't believe you are having the same problem. I think you are trying to do the same thing, or a similar thing, which is to embed the dll into your exe, but i don't think you are having the same problem.

I think you have a more basic problem: The ZipFile type is not known to the compiler. The first question, is, of course, why did you comment out the namespace declaration at the top of your source code? The line that reads "using Ionic.Zip" is the line that declares the ZipFile type (as well as all the others in the Ionic.Zip namespace) to the compiler. If you comment out that line, you will get unknown type errors at compile time.

I think the error message you posted must be a translation, because it doesn't sound familiar to me. But I'm pretty sure you need to include the namespace declaration in order to successfully compile. Embedding the dll allows you to avoid distributing the dll separately at runtime; it does not change the compile-time requirements for namespace declaration, and assembly references.

Good luck.
Oct 5, 2010 at 4:07 PM

Hi,


Thank you for your response and your time given to my problem.

So, yes I translated my error generated by Visual Studio, it was a temporary warning message.As the title of this post, I try to embed the DLL in my project but I can not.
As the example above,  there haven't  "using Ionic.Zip", so I put the line a comment. Now I understand that it is important to put this line for compiler.

I give you my source file if you have time to find and solve my problem, I'd be very grateful for some help.

My Embedded DLL Test Project :)

Coordinator
Oct 6, 2010 at 1:39 PM
Sorry, I don't have a computer with Visual Studio available to me at the moment, so I cannot do this for you. I CAN advise you, though.

At this point, I don't know the problem we're trying to solve.
Feb 8, 2011 at 2:57 AM

I made a class file that you can copy paste into your project and use it to call the basic Zip and Unzip Methods using the Ionic.Zip.Reduced.dll. 

All that is needed is that you include Ionic.Zip.Reduced.dll into your project and you set it as an embedded resource.  Then just add this code into your project.

And from your calling class, you can just call ZIPPER.CreateZipFile(zipfileName, datafileName) and ZIPPER.UnzipFile(zipfilename, unzipFileLocation).  If you need

any other methods from the DLL, you should be able to follow the code fairly easily (it's commented) to implement whatever methods you were looking for.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ZIPPER
{
   public static class ZipReflection
    {
        public static string ErrorMessage { get; set; }

        public static bool CreateZipFile(string zipFileName, string dataFileName)
        {
            try
            {
                ErrorMessage = string.Empty;

                //Get the name of the current executing assembly
                string assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

                //Specify the embedded resource DLL
                string dllName = "Ionic.Zip.Reduced.dll";

                //Build complete embedded resource name
                string embeddedResourceName = assemblyName + "." + dllName;

                //Retrieve the embedded DLL as a stream and then convert that stream into a byte array
                System.IO.Stream objStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(embeddedResourceName);
                byte[] rawBytes = new byte[objStream.Length];
                objStream.Read(rawBytes, 0, System.Convert.ToInt32(objStream.Length));
                objStream.Close();

                //Load the embedded DLL as an assembly by passing the byte array into the Load method
                System.Reflection.Assembly assembly = System.AppDomain.CurrentDomain.Load(rawBytes);

                //Retrieve the ZipFile type from assembly and create a new instance of it
                Type zipFileType = assembly.GetType("Ionic.Zip.ZipFile");
                object zipFileObject = Activator.CreateInstance(zipFileType);

                //Create object array of parameters to be sent to reflected method
                object[] methodParams = { dataFileName, string.Empty };

                //Invoke the AddFile method on the zipFileObject and pass in parameter array
                zipFileType.InvokeMember("AddFile", System.Reflection.BindingFlags.InvokeMethod, null, zipFileObject, methodParams);

                //Create object array of parameters to be sent to reflected method
                methodParams = new object[] { zipFileName };

                //Invoke the Save method on the zipFileObject and pass in parameter array
                zipFileType.InvokeMember("Save", System.Reflection.BindingFlags.InvokeMethod, null, zipFileObject, methodParams);

                //Invoke the Dispose method clean up any used resources
                zipFileType.InvokeMember("Dispose", System.Reflection.BindingFlags.InvokeMethod, null, zipFileObject, null);

                return true;
            }
            catch (Exception ex)
            {
                ErrorMessage = ex.Message;
                if (ex.InnerException != null)
                    ErrorMessage = ErrorMessage + System.Environment.NewLine + ex.InnerException.Message;
                return false;
            }
        }

        public static bool UnzipFile(string zipFileName, string unzipFileLocation)
        {
            try
            {
                ErrorMessage = string.Empty;

                //Get the name of the current executing assembly
                string assemblyName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

                //Specify the embedded resource DLL
                string dllName = "Ionic.Zip.Reduced.dll";

                //Build complete embedded resource name
                string embeddedResourceName = assemblyName + "." + dllName;

                //Retrieve the embedded DLL as a stream and then convert that stream into a byte array
                System.IO.Stream objStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(embeddedResourceName);
                byte[] rawBytes = new byte[objStream.Length];
                objStream.Read(rawBytes, 0, System.Convert.ToInt32(objStream.Length));
                objStream.Close();

                //Load the embedded DLL as an assembly by passing the byte array into the Load method
                System.Reflection.Assembly assembly = System.AppDomain.CurrentDomain.Load(rawBytes);

                //Retrieve the ZipFile type from assembly and create a new instance of it
                Type zipFileType = assembly.GetType("Ionic.Zip.ZipFile");
                object zipFileObject = Activator.CreateInstance(zipFileType);

                //Retrieve the ExtractExistingFileAction enumeration type from assembly
                Type zipEnumerationType = assembly.GetType("Ionic.Zip.ExtractExistingFileAction");

                //Retrieve specific enums from zipEnumeration and get its value
                System.Reflection.FieldInfo zipEnum1 = zipEnumerationType.GetField("OverwriteSilently");
                //System.Reflection.FieldInfo zipEnum2 = zipEnumerationType.GetField("DoNotOverwrite");
                //System.Reflection.FieldInfo zipEnum3 = zipEnumerationType.GetField("InvokeExtractProgressEvent");
                //System.Reflection.FieldInfo zipEnum4 = zipEnumerationType.GetField("Throw");
                //int enumValue = (int)zipEnum1.GetValue(zipEnumerationType);
                //object newEnum = Enum.ToObject(zipEnumerationType, enumValue);
                object enumValue = zipEnum1.GetValue(zipEnumerationType);

                //Create object array of parameters to be sent to reflected method
                object[] methodParams = { zipFileName };

                //Invoke the Read method on the zipFileObject and pass in parameter array 
                //Return the result back into the zipFileObject  [ie. Zip MyZip.Read()]
                zipFileObject = zipFileType.InvokeMember("Read", System.Reflection.BindingFlags.InvokeMethod, null, zipFileObject, methodParams);

                //Create object array of parameters to be sent to reflected method
                methodParams = new object[] { unzipFileLocation, enumValue };

                //Invoke the ExtractAll method on the zipFileObject and pass in parameter array 
                zipFileType.InvokeMember("ExtractAll", System.Reflection.BindingFlags.InvokeMethod, null, zipFileObject, methodParams);

                //Invoke the Dispose method so connection to the Zipfile is released so the file can be deleted
                zipFileType.InvokeMember("Dispose", System.Reflection.BindingFlags.InvokeMethod, null, zipFileObject, null);
                
                return true;

            }
            catch (Exception ex)
            {
                ErrorMessage = ex.Message;
                if (ex.InnerException != null)
                    ErrorMessage = ErrorMessage + System.Environment.NewLine + ex.InnerException.Message;
                return false;
            }
        }
    }
}
Feb 21, 2011 at 8:59 AM

Thanks Simcoder,

I despaired at not finding a solution !

I no longer work on the project that uses DotNetZip but it's interest for another new project, so thank you very much !