Adding ICSharpCode.SharpZipLib.dll to exe as embedded resource

bigfoot3d

Well-known member
Joined
Mar 11, 2007
Messages
56
Location
New Orleans, LA
Programming Experience
3-5
The project that I am currently working on uses the ICSharpCode.SharpZipLib implementation.

I am going to embed the dll file as a resource file, but I am not sure how to reference it so that I do not need to include the DLL file when distributing the exe.

When I used it as a simple reference file I could easily use
VB.NET:
Imports ICSharpCode.SharpZipLib.Checksums
Imports ICSharpCode.SharpZipLib.Zip
Imports ICSharpCode.SharpZipLib.GZip

However when I remove the reference the lines above throw warnings such as:

Namespace or type specified in the Imports 'ICSharpCode.SharpZipLib.Checksums' doesn't contain any public member or cannot be found. Make sure the namespace or the type is defined and contains at least one public member. Make sure the imported element name doesn't use any aliases.

Along with 'ICSharpCode.SharpZipLib.Zip' and 'ICSharpCode.SharpZipLib.GZip'

And lines such as
VB.NET:
Dim strmZipStream As ZipOutputStream
strmZipStream = New ZipOutputStream(strmZipFile)

Dim myZipEntry As ZipEntry
myZipEntry = New ZipEntry("ZippedFile")
are no longer valid because "ZipOutputStream" and "ZipEntry" are no longer defined.

How would I correctly reference the embedded DLL files so as to make the warnings and errors go away?

Thanks once again!
 
You would have to declare the objects as type Object and use reflection to load the assembly and create instances, then take advantage of Late-binding feature to use them. Same is done here with ADOX: http://www.vbdotnetforums.com/showthread.php?t=17903 Compared to that example My.Resources in .Net 2.0 will get you the resource byte array to load instead of using the getResource method.
 
So..

Thanks John, but this brings me to another question.

So do you mean replace this line:
VB.NET:
ICSharpCode = Reflection.Assembly.Load(getResource("ICSharpCode.SharpZipLib.dll"))
with this:
VB.NET:
ICSharpCode = Reflection.Assembly.Load(My.Resources.ICSharpCode.SharpZipLib.dll)

If so I am getting this error.

'ICSharpCode' is not a member of 'Resources'.


I also run into a problem with these lines:

VB.NET:
Dim ZipOutputStream As Object = ICSharpCode.CreateInstance("ICSharpCode.SharpZipLib.Zip.ZipOutputStream")

Dim strmZipStream As ZipOutputStream
strmZipStream = New ZipOutputStream(strmZipFile)

The error is: "Type 'ZipOutputStream' is not defined."

Is it possible to still treat it like a regular class? Too bad I couldn't include the original class files.
 
Last edited:
Your resource is probably not named "ICSharpCode.SharpZipLib.dll", what options do you get when typing "my.resources." ? You can also review the Resources page and see what name it has. When I add this library it is named "ICSharpCode_SharpZipLib". Other than that you have understood the point of doing assembly.load(my.res...)
The error is: "Type 'ZipOutputStream' is not defined."
You have to declare the variable as type Object.
Is it possible to still treat it like a regular class?
No, if you by 'regular' mean strongly typed variables and early-binding.
 
The usual way to write late-binding code (not uncommon with Office automation targeting multiple versions) is to add the reference and write all the code as normal and make sure it works, then you remove the reference and change all "error" variables to Object and add the reflection code to create instances. Assembly defined constants you have to redefine in your own code. Also only load the assembly once, else it will be loaded as multiple copies, it can't be unloaded from current app domain without exiting the app.

Also mind you, using an installer is much better, it is bad practice to use reflection and late-binding for the reason you say. (still I help you because this is useful to know:))
 
First of all:

The two options i get when typing my.resources. are "Culture" & "ResourceManger"

You have to declare the variable as type Object.

Second:

Didn't I declare it here as type object using
VB.NET:
Dim ZipOutputStream As Object = ICSharpCode.CreateInstance("ICSharpCode.SharpZipLib.Zip.ZipOutputStream")

Thanks
 
1. You haven't added it to application resources. Go to Project Properties, Resources tab, paste in the file here or use the "Add existing file" dialog here. You can also use the context menu on the Resources folder in Solution Explorer to add it.
2. You posted "Dim strmZipStream As ZipOutputStream", error "ZipOutputStream not defined".
 
Ahh, so its all coming together.

I already completely ran the code and it worked fine, but that was with the DLL, now I am trying to get it working with the DLL embedded.

First of all how would I go about fixing this:
VB.NET:
Dim ZipOutputStream As Object = ICSharpCode.CreateInstance("ICSharpCode.SharpZipLib.Zip.ZipOutputStream")

Dim strmZipStream As Object = ZipOutputStream
strmZipStream = New ZipOutputStream(strmZipFile)

Is there anyway I can throw it the NEW argument as such? or must I find another way around that.

VB.NET:
strmZipStream = New ZipOutputStream(strmZipFile)
Gives me:
Error 1 Type 'ZipOutputStream' is not defined.



Second:

Also mind you, using an installer is much better, it is bad practice to use reflection and late-binding for the reason you say. (still I help you because this is useful to know:))

Thank you for the help! I am doing it this way, because once everything is complete. I don't want the user to have to install anything. I want them to simply be able to run one simple(to them) executable without having to worry about extra files. For their peace of mind they can delete it after one use simply by deleting the executable. So I am making it so that its all embedded in once. This is the first and only thing that I am going to embed in this application.
 
Is there anyway I can throw it the NEW argument as such?
You have to use reflection to create instances (CreateInstance), there is an overload that allows constructor parameters specified as an array. Also Activator.CreateInstance can be used.
 
Its Coming Along

Ahh,

So this would be the result eh?

New Instance:
VB.NET:
Dim ZipOutputStream As Object = ICSharpCode.CreateInstance("ICSharpCode.SharpZipLib.Zip.ZipOutputStream")(strmZipFile)

If i wanted to keep the alterations down I would just add this line
VB.NET:
Dim strmZipStream As Object = ZipOutputStream

So as not to go change every strmZipStream instance.

Just double checking :)
 
That is not how you use CreateInstance method. Here an example:
VB.NET:
        Dim ax As System.Reflection.Assembly
        ax = System.Reflection.Assembly.Load(My.Resources.ICSharpCode_SharpZipLib)
        Dim t As Type = ax.GetType("ICSharpCode.SharpZipLib.Zip.ZipFile")
        Dim param() As Object = {"input.zip"}
        Dim ic As Object = Activator.CreateInstance(t, param)
The other stuff you say I don't understand.
 
Thanks!

JohnH,

That last post did the trick. It cleared up how to use the CreateInstance method as well.

I was able to use the executable file all by itself without having to have the DLL file with the exe.

I have option explicit on and option strict off.

Thanks once again for stepping me through this problem :D
 
Great, btw I just noticed that overload of Activator.CreateInstance specifies ParamArray so you don't have to create an array but just add up the parameters after the type similar to how "regular" constructors are used.
 
Back
Top