DotNetZip can be used from COM Environments
You can use DotNetZip from COM environments, via an IDispatch (late bound) interface. This means you can call into the DotNetZip library (the Ionic.Zip.dll assembly) from programming environments like PHP, Perl, Javascript, and VBScript (including old-school ASP pages), among others.
If you download and install the DotNetZip Runtime MSI package, it will set up DotNetZip for use with COM.
If for some reason you prefer to not use the MSI package, then you will need to perform some manual steps to enable DotNetZip for COM usage.
- open a CMD.exe prompt.
- Install into the GAC: gacutil -i Ionic.Zip.dll
- Register for COM use: regasm Ionic.Zip.dll
Notes: You will need to be local administrator in order to perform these steps. You need to perform those steps just once, on each computer where COM applications will run that use DotNetZip. The gacutil and regasm tools are included in the .NET Framework SDK.
Using the COM interface to DotNetZip
Via the COM exposure, applications written in COM-capable environments like old-school ASP using VBScript or Javascript, VBScript or Javascript running in Windows Script Host, PHP, Perl, and others, can create instances of the ZipFile class, add entries, and save archives, as any .NET application could. Most of DotNetZip's advanced features are available to these COM environments, including ZIP64 support, self-extracting archives, password-protected zip files, AES Encryption, spanned Zip files, and Unicode support. Beyond creating zips, COM environments can also read zips, modify them, or extract files from zip files.
Some of the advanced features of DotNetZip are not available through COM, including eventing, and streaming.
IDispatch
The key classes in DotNetZip that are exposed to COM are: ZipFile, ZipEntry, and the various ZipExceptions. These are all exposed via IDispatch interfaces - late binding only. (For those familiar with .NET, DotNetZip is decorated with ClassInterfaceType.AutoDispatch.) There is no explicit typelib exposed by DotNetZip.
COM supports calling instance methods and properties on .NET classes; COM does not support calling static methods on .NET objects via interop. To allow the various static methods on the ZipFile class, such as ZipFile.CheckZip() and ZipFile.IsZipFile(), to be called from COM, DotNetZip includes a ComHelper class. Instead of calling ZipFile.IsZipFile(), which is inaccessible to COM clients because it is a static method, COM clients should call Ionic.Zip.ComHelper.IsZipFile(). Use ComHelper as you would, any other class. The methods on the class are documented as with all the other classes in DotNetZip. If you are not programming DotNetZip from COM, you don't need the ComHelper class.
Overloaded Methods
COM does not directly support calling overloaded methods. In a .NET assembbly exposed to COM via interop, only the simplest method in a method group is directly available to COM callers. For example, consider ZipFile.AddFile. There are two overloads. Only the overload that accepts a single string will be accessible via the name "AddFile" to COM clients.
In most cases the thing you need to accomplish is achievable anyway. In the AddFile() case, setting the FileName on the entry after calling AddFile() will do the trick.
Also, the overloaded methods are available, via "mangled" names: each successive overload gets a numeric suffix. Consider the ZipFile.ExtractSelectedEntries method group; there are 5 overloads. The first, simplest, is available via the name ExtractSelectedEntries. Then, additional overloads are available via ExtractSelectedEntries_2, ExtractSelectedEntries_3, and so on. The same is true for other overloaded methods on the ZipFile and ZipEntry classes.
For the ZipFile class:
Method Overload | IDispatch name |
AddItem(string) | AddItem |
AddItem(string, string) | AddItem_2 |
AddFile(string) | AddFile |
AddFile(string, string) | AddFile_2 |
UpdateFile(string) | UpdateFile |
UpdateFile(string, string) | UpdateFile_2 |
UpdateDirectory(string) | UpdateDirectory |
UpdateDirectory(string, string) | UpdateDirectory_2 |
UpdateItem(string) | UpdateItem |
UpdateItem(string, string) | UpdateItem_2 |
AddEntry(string,string) | AddEntry |
AddEntry(string,string,Encoding) | AddEntry_2 |
AddEntry(string,Stream) | AddEntry_3 |
AddEntry(string,byte[]) | AddEntry_4 |
UpdateEntry(string,string) | UpdateEntry |
UpdateEntry(string,string,Encoding) | UpdateEntry_2 |
UpdateEntry(string,Stream) | UpdateEntry_3 |
UpdateEntry(string,byte[]) | UpdateEntry_4 |
AddDirectory(string) | AddDirectory |
AddDirectory(string,string) | AddDirectory_2 |
RemoveEntry(ZipEntry) | RemoveEntry |
RemoveEntry(string) | RemoveEntry_2 |
ExtractAll(string) | ExtractAll |
ExtractAll(string, bool) | ExtractAll_2 |
ExtractAll(string, ExtractExistingFileAction) | ExtractAll_3 |
Save() | Save |
Save(string) | Save_2 |
Save(Stream) | Save_3 |
AddSelectedFiles(string) | AddSelectedFiles |
AddSelectedFiles(string, bool) | AddSelectedFiles_2 |
AddSelectedFiles(string, string) | AddSelectedFiles_3 |
AddSelectedFiles(string, string, bool) | AddSelectedFiles_4 |
AddSelectedFiles(string, string, string) | AddSelectedFiles_5 |
AddSelectedFiles(string, string, string, bool) | AddSelectedFiles_6 |
RemoveSelectedEntries(string) | RemoveSelectedEntries |
AddSelectedFiles(string, string) | RemoveSelectedEntries_2 |
ExtractSelectedEntries(string) | ExtractSelectedEntries |
ExtractSelectedEntries(string, ExtractExistingFileAction) | ExtractSelectedEntries_2 |
ExtractSelectedEntries(string, string) | ExtractSelectedEntries_3 |
ExtractSelectedEntries(string, string, string) | ExtractSelectedEntries_4 |
ExtractSelectedEntries(string, string, string, ExtractExistingFileAction) | ExtractSelectedEntries_5 |
SaveSelfExtractor(string, SelfExtractorFlavor) | SaveSelfExtractor |
SaveSelfExtractor(string, SelfExtractorFlavor, string) | SaveSelfExtractor_2 |
SaveSelfExtractor(string, SelfExtractorFlavor, string, string) | SaveSelfExtractor_3 |
For the ZipEntry class:
Method Overload | IDispatch name |
Extract() | Extract |
Extract(ExtractExistingFileAction) | Extract_2 |
Extract(Stream) | Extract_3 |
Extract(string) | Extract_4 |
Extract(string, ExtractExistingFileAction) | Extract_5 |
ExtractWithPassword(string) | ExtractWithPassword |
ExtractWithPassword(string,string) | ExtractWithPassword_2 |
ExtractWithPassword(ExtractExistingFileAction,string) | ExtractWithPassword_3 |
ExtractWithPassword(string, ExtractExistingFileAction, string) | ExtractWithPassword_4 |
ExtractWithPassword(Stream, string) | ExtractWithPassword_5 |
The bad news is that the mappings between names and actual methods will change over releases of DotNetZip. This means depending on these names is a bit fragile, but it will work.
Destroy the ZipFile object
After you call .Dispose() on the ZipFile object, you should destroy it completely. In VBSCript, this is done by setting the object reference to Nothing.
The usage model for the ZipFile object
After you initialize a ZipFile object, you can't reuse the same object instance for another zip file. If for example, you have a set of 6 zip files, and you want to read and extract them in a loop, then you'll need to instantiate a new ZipFile object to read each one. You should call Dispose() on each one when you're finished, and then set it to null/Nothing.
For enumerations
DotNetZip exposes various enumerations to specify behavior in the interface - for example, the Ionic.Zlib.CompressionLevel enum, and the Ionic.Zip.ExtractExistingFileAction enum. Enums are not available to IDispatch clients. COM applications that need to use enum values can simply use the integer equivalent for those enums. In most cases those integer values are specified in the documentation for the enum. For example, for Ionic.Zip.ExtractExistingFileAction, the value of Throw is 0, while OverwriteSilently is 1.
Some examples follow.
Using DotNetZip in PHP
This is a PHP script that dynamically creates a ZIP file on the server, then downloads it to the requesting client. The Zip archive will use 256-bit AES encryption.
1$fname = "zip-generated-from-php-" . date('Y-m-d-His') . ".zip"; 2$zipOutput = "c:\\temp\\" . $fname; 3$zip = new COM("Ionic.Zip.ZipFile"); 4$zip->Name = $zipOutput; 5$dirToZip= "c:\\temp\\psh"; 6$zip->Encryption = 3; 7$zip->Password = "AES-Encryption-Is-Secure"; 8$zip->AddDirectory($dirToZip); 9$zip->Save(); 10$zip->Dispose(); 11 12if (file_exists($zipOutput)) 13{ 14 header('Cache-Control: no-cache, must-revalidate'); 15 header('Content-Type: application/x-zip'); 16 header('Content-Disposition: attachment; filename=' . $fname); 17 header('Content-Length: ' . filesize($zipOutput)); 18 readfile($zipOutput); 19 unlink($zipOutput); 20}
Using DotNetZip in Javascript
This example dynamically creates a zipfile, using AES 256-bit encryption.
1var filename = "C:\\temp\\ZipFile-created-from-javascript-" + generateTimestamp() + ".zip"; 2 3try 4{ 5 WScript.echo("Instantiating a ZipFile object..."); 6 var zip = new ActiveXObject("Ionic.Zip.ZipFile"); 7 8 WScript.echo("setting the encryption..."); 9 // 3 = AES256, 2 = AES128, 1 = PKZIP, 0 = none 10 zip.Encryption = 3; 11 12 WScript.echo("setting the password..."); 13 zip.Password = "This is the Password."; 14 15 WScript.echo("adding a selection of files..."); 16 zip.AddSelectedFiles("*.js"); 17 zip.AddSelectedFiles("*.vbs"); 18 19 WScript.echo("setting the save name..."); 20 zip.Name = filename; 21 22 WScript.echo("Saving..."); 23 zip.Save(); 24 25 WScript.echo("Disposing..."); 26 zip.Dispose(); 27 28 WScript.echo("Done."); 29} 30catch (e2) 31{ 32 WScript.echo(e2.number + ": " + e2.name); 33 WScript.echo(e2.message); 34}
This example lists the entries in a zipfile.
1var filename = "C:\\temp\\CompressedData.zip"; 2 3try 4{ 5 WScript.echo("Instantiating a ZipFile object..."); 6 var zip = new ActiveXObject("Ionic.Zip.ZipFile"); 7 8 WScript.echo("Initialize (Read)...(" + filename + ")"); 9 zip.Initialize(filename); 10 11 WScript.echo("listing entries..."); 12 var e = new Enumerator(zip); 13 for (; !e.atEnd(); e.moveNext()) 14 { 15 var entry= e.item(); 16 WScript.Echo (" " + entry.FileName); 17 } 18 19 WScript.echo("Disposing...") 20 zip.Dispose(); 21 22 WScript.echo("Done."); 23} 24catch (e2) 25{ 26 WScript.echo(e2.number + ": " + e2.name); 27 WScript.echo(e2.message); 28}
This example checks a ZipFile using the ComHelper class.
1function checkZip(filename) 2{ 3 var obj = new ActiveXObject("Ionic.Zip.ComHelper"); 4 return obj.IsZipFile(filename); 5} 6 7function checkZipWithExtract(filename) 8{ 9 var obj = new ActiveXObject("Ionic.Zip.ComHelper"); 10 return obj.IsZipFileWithExtract(filename); 11} 12 13function main() 14{ 15 var result; 16 var args = WScript.Arguments; 17 18 if (args.Length == 1) 19 { 20 result = checkZip(args(0)); 21 } 22 else if (args.Length == 2 && args(0) == "-x") 23 { 24 result = checkZipWithExtract(args(1)); 25 } 26 else 27 { 28 WScript.Echo("TestCheckZip.js - check a zipfile using Javascript."); 29 WScript.Echo(" usage: TestCheckZip.js [-x] <pathToZip>"); 30 WScript.Quit(1); 31 } 32 33 WScript.Echo((result==0)?"That zip is not OK":"That zip is OK"); 34 WScript.Quit(0); 35} 36 37main();
Using DotNetZip in VBScript
This example creates a zipfile, using AES 256-bit encryption.
1dim filename 2filename = "C:\temp\ZipFile-created-from-VBScript.zip" 3 4WScript.echo("Instantiating a ZipFile object...") 5dim zip 6set zip = CreateObject("Ionic.Zip.ZipFile") 7 8WScript.echo("Setting the encryption...") 9' 3=AES256, 2=AES128, 1=PKZIP, 0=none 10zip.Encryption = 3 11 12WScript.echo("setting the password...") 13zip.Password = "This is the Password." 14 15WScript.echo("adding a selection of files...") 16zip.AddSelectedFiles "*.js" 17zip.AddSelectedFiles "*.vbs" 18 19WScript.echo("setting the save name...") 20zip.Name = filename 21 22WScript.echo("Saving...") 23zip.Save 24 25WScript.echo("Disposing...") 26zip.Dispose 27 28zip = Nothing 29 30WScript.echo("Done.")
This example extracts all entries from a zipfile.
1WScript.echo("Instantiating a ZipFile object...") 2dim zip 3set zip = CreateObject("Ionic.Zip.ZipFile") 4 5WScript.echo("Initialize (Read)...") 6zip.Initialize("CompressedData.zip") 7 8WScript.echo("setting the password for extraction...") 9zip.Password = "This is the Password." 10 11WScript.echo("extracting all files...") 12zip.ExtractAll "DotNetZip-extract" 13 14WScript.echo("Disposing...") 15zip.Dispose 16 17WScript.echo("Done.")
This example lists the entries in a zipfile, and extracts some of them.
1WScript.echo("") 2Dim zip 3WScript.echo("Instantiating a ZipFile object...") 4Set zip = CreateObject("Ionic.Zip.ZipFile") 5 6WScript.echo("Initialize (Read)...") 7zip.Initialize filename 8 9Set fso = CreateObject("Scripting.FileSystemObject") 10If Not fso.FolderExists("unpack") Then 11 fso.CreateFolder("unpack") 12End If 13 14' Any call to ZipEntry.Extract() will put files into the 15' current working directory. So set it here: 16Set objShell = CreateObject("Wscript.Shell") 17objShell.CurrentDirectory = "unpack" 18 19WScript.echo("listing...") 20For Each entry in zip 21 WScript.echo(" " & entry.FileName) 22 ext = Right(entry.FileName,4) 23 If (ext = ".vbs") Then 24 ' set password for extraction if necessary 25 entry.Password = "This is the Password." 26 entry.Extract 27 End If 28Next 29 30WScript.echo("Disposing...") 31zip.Dispose 32 33WScript.echo("Done.")
This example extracts selected entries from a zip archive, via the ExtractSelectedEntries overload. It uses the mangled name to access the method, as described above.
1Sub extractZip() 2 If Not (extractLocation = "") Then 3 Dim OverwriteSilently 4 OverwriteSilently = 1 5 6 Dim zip 7 Set zip = CreateObject("Ionic.Zip.ZipFile") 8 9 zip.Initialize filename 10 11 If password <> "" Then 12 zip.Password = password 13 End If 14 15 zip.ExtractSelectedEntries_5 "name = *.xml", Null, extractLocation, OverwriteSilently 16 17 zip.Dispose 18 zip = Nothing 19 End If 20 21End Sub