I wanted to create a Windows scheduled task to regularly compress a log file on several servers. The simple solution would be to install a command-line ZIP program and write a CMD script. After some searching, it became more interesting to write a VBScript program that uses the Compressed (zipped) folder
feature in the Windows Explorer.
The result is the ZipFile VBA and VBScript program at the end of this posting. I wrote and tested the VBA program first then converted it to VBScript. You can run the VBScript program by providing the path of the ZIP archive and the path of the file to compress.
The program first deletes any existing ZIP file with the same name and creates an empty ZIP folder (actually a file). Then it calls the Windows Shell CopyHere() method to add a new file into the ZIP folder. The CopyHere() method doesn't block (i.e. it returns control immediately to the script) so the program polls the ZIP folder once a second to check if a file has been added (the ZIP folder's Items.Count is incremented). Without this polling loop, the program ends before the file is added (you can test it by commenting out the polling loop statements and archiving a large file).
The numeric argument for the CopyHere() method is a bit-string to avoid displaying the Windows Compressing...
progress window. However, I found that the progress window is still displayed but it doesn't seem to affect the ZIP archive when the program is run as a scheduled task (whew!).
References
VBA Version
Attribute VB_Name = "ZipFile" Option Explicit Option Base 0 Declare Sub Sleep Lib "kernel32" (ByVal dwMiliseconds As Long) 'VBA add these references '1. Microsoft Scripting Runtime '2. Microsoft Shell Controls and Automation Public Sub MakeZip(zipPath As String, filePath As String) MakeEmptyZip zipPath AddFile zipPath, filePath End Sub Private Sub AddFile(zipPath As String, filePath As String) Dim sh As Shell32.Shell, fdr As Shell32.Folder, cntItems As Integer 'cnt = Count Set sh = CreateObject("Shell.Application") Set fdr = sh.Namespace(zipPath) cntItems = fdr.Items.Count fdr.CopyHere filePath, 4 + 16 + 1024 Do Sleep 1000 Loop Until cntItems < fdr.Items.Count Set fdr = Nothing Set sh = Nothing End Sub Private Sub MakeEmptyZip(zipPath As String) Dim fso As Scripting.FileSystemObject Set fso = CreateObject("Scripting.FileSystemObject") If fso.FileExists(zipPath) Then fso.DeleteFile zipPath End If fso.CreateTextFile(zipPath).Write "PK" & Chr(5) & Chr(6) & String(18, Chr(0)) Set fso = Nothing End Sub 'Entry MakeZip WScript.Arguments(0), WScript.Arguments(1)
VBSCript Version
Option Explicit 'VBA add these references '1. Microsoft Scripting Runtime '2. Microsoft Shell Controls and Automation Public Sub MakeZip(zipPath, filePath) MakeEmptyZip zipPath AddFile zipPath, filePath End Sub Private Sub AddFile(zipPath, filePath) Dim sh, fdr, cntItems Set sh = CreateObject("Shell.Application") Set fdr = sh.Namespace(zipPath) cntItems = fdr.Items.Count fdr.CopyHere filePath, 4 + 16 + 1024 Do WScript.Sleep 1000 Loop Until cntItems < fdr.Items.Count Set fdr = Nothing Set sh = Nothing End Sub Private Sub MakeEmptyZip(zipPath) Dim fso Set fso = CreateObject("Scripting.FileSystemObject") If fso.FileExists(zipPath) Then fso.DeleteFile zipPath End If fso.CreateTextFile(zipPath).Write "PK" & Chr(5) & Chr(6) & String(18, Chr(0)) Set fso = Nothing End Sub MakeZip WScript.Arguments(0), WScript.Arguments(1)
Hello, i tried to edit the zipPath to E:\Sample\ and filePath to E:\Test but it doesnt work. What happen?
ReplyDeleteThanks
zipPath should be the name of a file, not a folder.
ReplyDeleteSo this code will not work if im going to zip a folder?
ReplyDeleteI want to zip a folder and place it within that folder.
Im sorry but im just a beginner in vbscript.
The program will zip a folder. Set:
ReplyDelete1. zipPath = E:\Sample\Test.zip
2. filePath = E:\Test
It doesnt seem to work. I added the lines below.
ReplyDeleteIm sorry i need help for my project.
Dim zipPath, filePath
zipPath = "C:\Users\Name\Documents\Files\Sample\Test.zip"
filePath = "C:\Users\Name\Documents\Files\Test"
Public Sub MakeZip(zipPath, filePath)
MakeEmptyZip zipPath
AddFile zipPath, filePath
End Sub
Looks like you have only declared MakeZip(). Just add a statement to call the subroutine:
ReplyDeleteMakeZip zipPath, filePath
Option Explicit
ReplyDelete'VBA add these references
'1. Microsoft Scripting Runtime
'2. Microsoft Shell Controls and Automation
Public Sub MakeZip(zipPath, filePath)
MakeEmptyZip zipPath
AddFile zipPath, filePath
End Sub
Private Sub AddFile(zipPath, filePath)
Dim sh, fdr, cntItems
Set sh = CreateObject("Shell.Application")
Set fdr = sh.Namespace(zipPath)
cntItems = fdr.Items.Count
fdr.CopyHere filePath, 4 + 16 + 1024
Do
WScript.Sleep 1000
Loop Until cntItems < fdr.Items.Count
Set fdr = Nothing
Set sh = Nothing
End Sub
Private Sub MakeEmptyZip(zipPath)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists(zipPath) Then
fso.DeleteFile zipPath
End If
fso.CreateTextFile(zipPath).Write "PK" & Chr(5) & Chr(6) & String(18, Chr(0))
Set fso = Nothing
End Sub
I copy the whole code and add the following line
zipPath = "C:\Users\Name\Documents\Files\Sample\Test.zip"
filePath = "C:\Users\Name\Documents\Files\Test"
Is this correct?
You need to add a statement to call the MakeZip subroutine otherwise nothing will happen.
DeleteHi,
ReplyDeleteIs it possible to zip a folder with the same directory?
Example:
folderToZip = E:\Test\FolderIWanttoZip
destination = E:\Test\FolderIWanttoZip.zip
Try it. I don't think it's a good idea because the program may add the zip file into the zip file.
DeleteHi Mister,
ReplyDeleteI have here my code:
Dim objFSO, objShell
Dim strPath, strFolder, strZip
Dim objOutput
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("Shell.Application")
Set objOutput = objFSO.CreateTextFile("Output.txt")
ObjOutput.WriteLine("Type,File Name,File Path")
strPath = objFSO.GetAbsolutePathName(".")
strFolder = strPath & ".zip"
'strZip = strFolder & ".zip"
WScript.Echo("Completed")
'GetFolder strFolder
ZipFolder strFolder
Function ZipFolder(strZip)
Dim objFolder, objFolderName, objZip
strZip = Replace(strZip,"\","_")
strZip = Right(strZip, Len(strZip) - 3)
'Basis for zip File
Set objFolder = objFSO.CreateTextFile(strZip, True)
objFolder.Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
' Add the folder to the Zip
Set objZip = objShell.NameSpace(strZip)
Set objFolderName = objShell.NameSpace(strZip)
objZip.CopyHere(objFolderName.Items)
WScript.Sleep 2000
End Function
It now creates a zip folder to where you run the script but its empty. It creates an error "ObjRequired".
Objective is i want to create a zip folder to where the script was ran and i want to copy the files inside the zip folder except for the this script? Is it possible? or do you have any suggestions? Please enlighten me. Thanks. :) Please help me