Compressed Folders in WSH - Adding and Extracting files
(Page 4 of 4 )
It’s probably a good idea to package this code in a function. You also make it a little more friendly by using a With structure to eliminate some redundancies. Here’s what my function looks like.
Function NewCompressedFolder(strPath)
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateNotExist = 1
Const adSaveCreateOverwrite = 2
With CreateObject("ADODB.Stream")
.Open
.Type = adTypeText
.WriteText ChrB(&h50) & ChrB(&h4B) & ChrB(&h5) & ChrB(&h6)
For i = 1 To 18
.WriteText ChrB(&h0)
Next
.SaveToFile strPath, adSaveCreateNotExist
.Close
.Open
.Type = adTypeBinary
.LoadFromFile strPath
.Position = 2
arrBytes = .Read
.Position = 0
.SetEOS
.Write arrBytes
.SaveToFile strPath, adSaveCreateOverwrite
.Close
End With
End Function
Finally, you probably wouldn’t be trying to create a compressed folder if you had no intentions of using it. Remember, compressed folder support is native to the Windows Shell, so we’ll need to use its scripting object to work with the file. This isn’t as hard as it sounds. You can see that Windows Explorer treats these zip files as folders. As it turns out, that extends to the Shell object as well.
Function AddFile(strFolder, strFile, blnKeepOriginal)
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(strFolder)
intCount = objFolder.Items.Count
Select Case blnKeepOriginal
Case True
objFolder.CopyHere strFile, 256
Case False
objFolder.MoveHere strFile, 256
End Select
Do Until objFolder.Items.Count = intCount + 1
WScript.Sleep 200
Loop
End Function
My function requires that you provide the path to the zip file, the path to the file to add, and a Boolean value that indicates whether to keep the original file. It uses the Shell object’s NameSpace method to return a folder object for the zip file. It then either copies or moves a file into the compressed folder based upon the Boolean value that was supplied.
Here’s the catch: a Shell Copy or a Shell Move process will not halt execution of the script. Therefore, you will need to create a timer routine to pause the script until it completes. I’ve used a simple mechanism that checks the number of files in the zip folder beforehand and loops until that number is increased by 1.
Extracting files from a compressed folder is a matter of copying them back out using the Shell object. I’ve chosen to create an ExtractAll method that will dump a compressed folder’s contents to a new folder.
Function ExtractAll(strZipFile, strFolder)
Set objShell = CreateObject("Shell.Application")
Set objFso = CreateObject("Scripting.FileSystemObject")
If Not objFso.FolderExists(strFolder) Then
objFso.CreateFolder(strFolder)
End If
intCount = objShell.NameSpace(strFolder).Items.Count
Set colItems = objShell.NameSpace(strZipFile).Items
objShell.NameSpace(strFolder).CopyHere colItems, 256
Do Until objShell.NameSpace(strFolder).Items.Count = intCount + colItems.Count
WScript.Sleep 200
Loop
End Function
This is very similar to the AddFile function I just showed you. Here, I’m copying files out of the compressed folder using the Shell object. This time my timer relies on a file count of the destination folder. Since the folder could have existing files, I check the number of files beforehand and then wait until it is increased by the number of items in the compressed folder.
This is not a perfect solution. If a file with the same name exists, whether it is overwritten or not, the item count in the destination folder will be one short.
You will also notice that I’m not supplying each item individually, nor am I looping through the items. I’m simple providing the whole collection to the CopyHere method and letting the Shell object sort it out. Providing a collection to the Shell object’s CopyHere or MoveHere methods will copy or move a group of files in a single process.
If you want to allow your users to select a destination folder for the extraction process, you could use the function above along with a Browse For Folder dialog box, or you could simply harness the Windows Shell’s Compressed Folder support once again by invoking the Extraction Wizard.
Function ExtractAllW(strZipFile)
Set objShell = CreateObject("Shell.Application")
Set WshShell = CreateObject("WScript.Shell")
objShell.NameSpace(strZipFile).Items.Item.InvokeVerb("Extract &All...")
Do While WshShell.AppActivate("Extraction Wizard")
WScript.Sleep 200
Loop
End Function
This time I’ve named the function slightly differently, and we only need to provide a single string parameter containing a path to the compressed folder. A little Shell magic is used to conjure the Extraction Wizard from the compressed folder’s context menu.
In order to create a timer loop this time, I’ve employed the WshShell object. Its AppActivate method will bring a specified window into focus. This method returns true if it completes successfully and false otherwise. This Boolean return value can be used to determine whether or not the Extraction Wizard is still open.
So there you have it. You can create compressed folders from within WSH using only native objects. I’ve provided several very useful workarounds in this article that can be applied in countless other ways. Take time to really play with them. Until next time, keep coding!
| DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware. |