mvd
mvd

Reputation: 2720

Windows batch file calling vbscript doesn't wait for it finish

I have a VBScript that I am using to zip up some files. When called from a batch file, the batch doesn't wait for the script to finish, and you seem to need a sleep in the vbscript to give the zipping enough time, otherwise you end up with an empty or corrupt zip file. Is there any way to make the cscript execution be synchronous?

Here are the scripts:

Set objArgs = WScript.Arguments
InputFolder = objArgs(0)
ZipFile = objArgs(1)
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set objShell = CreateObject("Shell.Application")
Set source = objShell.NameSpace(InputFolder).Items
objShell.NameSpace(ZipFile).CopyHere(source)
wScript.Sleep 30000

Notice the sleep at the end which is necessary, but hacky since I don't know how long the actual zipping will take. And the batch file call:

CScript //B zipCOM.vbs %TEMPZIPDIR% %ARCHIVEFILE%

Upvotes: 1

Views: 1947

Answers (2)

MC ND
MC ND

Reputation: 70971

The zip folders operations are asynchronous. You need to wait for the code to end. This is a simple way to do it: wait until the lock on the file (hold by the zipping operation) has been released.

Option Explicit

Dim objArgs, InputFolder, ZipFile
    Set objArgs = WScript.Arguments
    InputFolder = objArgs.Item(0)
    ZipFile = objArgs.Item(1)

Dim fso
    Set fso = WScript.CreateObject("Scripting.FileSystemObject")
    fso.CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)

Dim objShell, source
    Set objShell = CreateObject("Shell.Application")
    Set Source = objShell.NameSpace(InputFolder).Items

    objShell.NameSpace(ZipFile).CopyHere( source )

    ' Wait for the operation to start
    WScript.Sleep 3000

    ' Loop until the file can be written 
Dim objFile
    On Error Resume Next
    Do While True
        Err.Clear
        Set objFile = fso.OpenTextFile( ZipFile, 8, False )
        If Err.Number = 0 Then
            objFile.Close
            Exit Do
        End If
        WScript.Sleep 100
    Loop 

Upvotes: 3

Nathan Rice
Nathan Rice

Reputation: 3111

Here is a function I wrote that might help you:

http://www.naterice.com/blog/template_permalink.asp?id=64

Function WindowsZip(sFile, sZipFile)
  'This script is provided under the Creative Commons license located
  'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
  'be used for commercial purposes with out the expressed written consent
  'of NateRice.com

  Set oZipShell = CreateObject("WScript.Shell")  
  Set oZipFSO = CreateObject("Scripting.FileSystemObject")

  If Not oZipFSO.FileExists(sZipFile) Then
    NewZip(sZipFile)
  End If

  Set oZipApp = CreateObject("Shell.Application")

  sZipFileCount = oZipApp.NameSpace(sZipFile).items.Count

  aFileName = Split(sFile, "\")
  sFileName = (aFileName(Ubound(aFileName)))

  'listfiles
  sDupe = False
  For Each sFileNameInZip In oZipApp.NameSpace(sZipFile).items
    If LCase(sFileName) = LCase(sFileNameInZip) Then
      sDupe = True
      Exit For
    End If
  Next

  If Not sDupe Then
    oZipApp.NameSpace(sZipFile).Copyhere sFile

    'Keep script waiting until Compressing is done
    On Error Resume Next
    sLoop = 0
    Do Until sZipFileCount < oZipApp.NameSpace(sZipFile).Items.Count
      Wscript.Sleep(100)
      sLoop = sLoop + 1
    Loop
    On Error GoTo 0
  End If
End Function

Sub NewZip(sNewZip)
  'This script is provided under the Creative Commons license located
  'at http://creativecommons.org/licenses/by-nc/2.5/ . It may not
  'be used for commercial purposes with out the expressed written consent
  'of NateRice.com

  Set oNewZipFSO = CreateObject("Scripting.FileSystemObject")
  Set oNewZipFile = oNewZipFSO.CreateTextFile(sNewZip)

  oNewZipFile.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)

  oNewZipFile.Close
  Set oNewZipFSO = Nothing

  Wscript.Sleep(500)
End Sub

Upvotes: 1

Related Questions