View Single Post
Old 06-12-2007, 06:44 PM
PrOpHeT's Avatar
PrOpHeT PrOpHeT is offline
Hopelessly confused...

* Expert *
Join Date: Mar 2001
Location: Tyler, Tx.
Posts: 3,055
Default Natively zipping Files in

Now this only works on XP/2003 server/(Not tested on vista, but should work)

Requires reference to shell32.dll in %windir%\system32

I recently had a scripting question concerning copying files with progress with VBS and dilettante was so kind as to point out that the shell object could be used to make explorer copy files instead of using typical file io.

I knew that the shell32 library could be utilized in .net as a com import, I have used it to manipulate windows before. So I decided to do a little playing.

A quick hex edit examination of a new zip file created in windows revealed that the file was simply a binary file with the header of “PK” and ENQ and an ACK character followed by a bunch of nulls, fairly easy to recreate to say the least.

Private Sub CreateZipFile(ByVal Filename As String) 'create a new empty zip file Dim Encoder As New System.Text.ASCIIEncoding Dim Header As String = "PK" & Chr(5) & Chr(6) Header = Header.PadRight(22, Chr(0)) My.Computer.FileSystem.WriteAllBytes(Filename, Encoder.GetBytes(Header), False) 'so what have we done here? 'we have created a blank zip file the same as right clicking and choosing 'new > Compressed (Zipped) folder, it must have the extension .zip for the 'trick to work. End Sub

Here is where the magic happens!
We use the explorer shell to copy the file instead of a typical src/dest file copy. Explorer recognizes the destination is a compressed file and inserts the input file/directory into it compressing on the fly the same as if you had chosen copy paste in explorer. The method works if Input is a file or a directory.

Private Sub ZipFile(ByVal Input As String, ByVal Filename As String) Dim Shell As New Shell32.Shell CreateZipFile(Filename) Shell.NameSpace(Filename).CopyHere(Input) End Sub

Now we can call

'take everything from the C:\Testfrom directory and compress it into the c:\ file ZipFile("c:\testfrom", "c:\")

Of course you could create your own method of enumerating files and folders to insert, this is just to show how they can be inserted into the compressed file.

I am still trying to figure out how to get the files back out, but if you simply need to archive something, prepare it for upload, etc... there seems no easier way and no thrid party controls needed.

What if you needed to zip from legacy VB?

Just as easy just some aditional code...

the folowing VBS file will do the same as the above .net code and can easily be ported to vb6

Compress "c:\testfrom" ,"c:\" Sub Compress(Input, ZipFile) Dim Shell : Set Shell = CreateObject("Shell.Application") Dim FSO : set FSO = CreateObject("Scripting.fileSystemObject") FSO.CreateTextFile(ZipFile, true).WriteLine "PK" & Chr(5) & Chr(6) & String(18, 0) Set ZipFile = Shell.NameSpace(ZipFile) <I know I shouldn't but it makes for less lines of code ;) ZipFile.CopyHere Input Do Until ZipFile.items.Count = 1 'important, makes the script not fall out and dispose of objects before they are done 'items.count is the amount of root items you anticipate to be in the zip file wscript.sleep 100 Loop Set Shell = Nothing Set FSO = Nothing Set ZipFile = Nothing End Sub

Now all of this is just rough concept at this point, but certainly you can see it has real potential. As I clean it up and wrap a real class around it with some flow and error control I will keep it posted, if anyone else plays with it and wants to contribute please do. This is a VERY common question here and worth the research.
When you earnestly believe you can compensate for a lack of skill by doubling your efforts, there's no end to what you can't do ;)

For the love of Gold...

Last edited by PrOpHeT; 06-12-2007 at 08:26 PM.
Reply With Quote