I'm writing a VBScript for SyncBack (backup utility) in which I am deleting old versions of a backup.
'' # if current version is greater than the total allowed number of versions,
'' # delete the oldest folder
If versionNumber > totalVersions Then
delDirNum = versionNumber - totalVersions
If delDirNum > 0 Then
DelFoldername = containerFileOrFolder & "\" & delDirNum & "_"
'' " # Ignore this line SO Prettify doesn't do VB very well.
If fso.FolderExists(DelFoldername) = True Then
WScript.Echo "Deleting: <" & DelFoldername & ">"
Set oFolder = objFileSystem.GetFolder(DelFoldername)
oFolder.Delete()
WScript.Sleep 2000
If fso.FolderExists(DelFoldername) = False Then
WScript.Echo "Deleted <" & DelFoldername & "> successfully"
Else
WScript.Echo "Could not delete <" & DelFoldername & ">"
End If
End If
End If
End If
However, occasionally the folder (that contains the old backup) which I am trying to delete takes longer that the 2 seconds at WScript.Sleep 2000 to remove and I was wondering if there was a way of making the script wait until the folder has been deleted before it prints out "Deleted <foldername> successfully".
Ideally I'd love something like:
While oFolder.IsDeleting() Then
WScript.Echo "Still deleting..."
WScript.Sleep 2000
Loop
But I'm well aware that that's probably not going to be the case.
While fso.FolderExists(DelFoldername)
WScript.Echo "Still deleting"
WScript.Sleep 1000
Wend
You could move the delete into it's own function and add a timeout. so if the folder is not deleted in a reasonable amount of time the function returns without deleting the folder. Something like this:
Function DeleteFolder(Folder, Timeout)
'Folder is the full file path of the folder
'Timeout is the amount of time to wait for the folder to be deleted (in seconds).
On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FolderExists(Folder) Then
fso.DeleteFolder Folder, True
start = Now()
do while fso.FolderExists(Folder) AND DateDiff("s",start,Now()) < Timeout
wscript.sleep 1000
Loop
End If
If fso.FolderExists(Folder) Then
DeleteFolder = False
Else
DeleteFolder = True
End If
End Function
Then call the function like this
If DeleteFolder("C:\New Folder", 5) Then
Wscript.Echo "Folder Deleted"
Else
Wscript.Echo "Folder could NOT be deleted"
End If
WARNING: Using On Error Resume Next is not recomended.
This command will cause all errors to be ignored, and should only be used under adult supervision.
Side effects may include: Strange errors in other parts of a script, unexpected script action, headache, dizziness, confusion, anger, or a sudden urge to curse. In rare cases this command has been known to cause bleeding from the eyes and ears. Using this command may lead to hair and job loss.
Loop sleep with counter, note assumes CScript host which makes the "Still Deleting" message a bit more palettable. The delay in the example is 30 seconds.
Dim loopCount : loopCount = 0
WScript.StdOut.Write "Deleting ."
Do While fso.FolderExists(DelFoldername) And loopCount < 30
WScript.Sleep 1000
WScript.StdOut.Write "."
loopCount = loopCount + 1
Loop
WScript.StdOut.Write vbCrLf
If fso.FolderExists(DelFolderName) Then
'' # Do stuff due to failure.
End If
Why not just keep checking to see if the folder still exists, and exit once it's gone?
' Do
' If folder does not exist, exit Do
' Loop
Related
I am using VBscript to scan folders, create zip files and add files to them (compress), but as I run my script on folders with a lot of files, I get the following error: "Compressed (zip) Cannot create output file"
my zip handling code is as follows:
Dim objFSO
Set objFSO= CreateObject("Scripting.FileSystemObject"
Function PreformZip(objFile,target,zip_name, number_of_file)
Set shell = CreateObject("WScript.Shell")
zip_target = target + "\" + zip_name +".zip"
If Not objFSO.FileExists(zip_target) Then
MakePathIfNotExist(target)
NewZip(zip_target)
Else
If number_of_file=0 Then
objFSO.DeleteFile(zip_target)
NewZip(zip_target)
End if
End If
Set zipApp = CreateObject("Shell.Application")
aSourceName = Split(objFile, "\")
sSourceName = (aSourceName(Ubound(aSourceName)))
zip_file_count = zipApp.NameSpace(zip_target).items.Count
zipApp.NameSpace(zip_target).Copyhere objFile, 16
On Error Resume Next
sLoop = 0
Do Until zip_file_count < zipApp.NameSpace(zip_target).Items.Count
Wscript.Sleep(100)
sLoop = sLoop + 1
Loop
On Error GoTo 0
End Function
Sub NewZip(zip)
Set new_zip = objFSO.CreateTextFile(zip)
new_zip.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)
new_zip.Close
Set new_zip = Nothing
WScript.Sleep(5000)
End Sub
Function MakePathIfNotExist(DirPath)
Dim FSO, aDirectories, sCreateDirectory, iDirectory
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FolderExists(DirPath) Then
Exit Function
End If
aDirectories = Split(DirPath, "\")
sCreateDirectory = aDirectories(0)
For iDirectory = 1 To UBound(aDirectories)
sCreateDirectory = sCreateDirectory & "\" & aDirectories(iDirectory)
If Not FSO.FolderExists(sCreateDirectory) Then
FSO.CreateFolder(sCreateDirectory)
End If
Next
End Function
Function Recursion(DirectoryPath)
Dim FSO : Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FolderExists(DirectoryPath) Then Exit Function
Call Recursion(FSO.GetParentFolderName(DirectoryPath))
FSO.CreateFolder(DirectoryPath)
End Function
I first thought I'm not waiting long enough after creating the zip, but I even tried it with 10 seconds wait after each zip and I still get the same error.
How can I solve it?
If there is no solution, is there an alternative way to make a zip? The script is not only for my own use so I don't want ro relay on a software which needs to be installed?
Although Folder.CopyHere method does not return a value and no notification is given to the calling program to indicate that the copy has completed, you could wait with next code snippet and I hope you can see proper (re)placement in your script:
On Error GoTo 0
zipApp.NameSpace(zip_target).Copyhere objFile _
, 4 +8 +16 +256 +512 +1024
Wscript.Sleep( 100)
On Error GoTo 0
Notice: no waiting Do..Loop, this Wscript.Sleep( 100) is sufficient to zip small files or start progress dialog box in case of huge files - and your script will wait for it...
Notice: no 'On Error Resume Next. Avoid invoking On Error Resume Next if you do not handle errors...
Flags used as follows.
Const FOF_SILENT = &h0004 'ineffective?
Const FOF_RENAMEONCOLLISION = &h0008 'ineffective?
Const FOF_NOCONFIRMATION = &h0010 '
Const FOF_SIMPLEPROGRESS = &h0100 'ineffective?
Const FOF_NOCONFIRMMKDIR = &h0200 '
Const FOF_NOERRORUI = &h0400 '
Unfortunately, in some cases, such as compressed (.zip) files, some option flags may be ignored by design (sic!) by MSDN!
If FOF_SILENT flag ineffective, then user could Cancel zipping process...
If FOF_RENAMEONCOLLISION flag ineffective, then newer file of the same name is not zipped, existing zip file keeps previous version without caution against; only existing folder brings on an extra error message...
Those could be fixed up as well, but it's subject of another question...
Well, after a great amount of research I found out that there is no possible way to fix this problem when using shell to perform zip.
I solved this issue by using za7.exe (7-zip) in the following way:
Dim zipParams
zipParams = "a -tzip"
Dim objShell: Set objShell = CreateObject("WScript.Shell")
command = zip_exe_location + " " + zipParams + " " + zip_target + " " + SourceFile
objShell.Run Command, 0 ,true
the "a" in the zip parameters means "add to file" and -tzip sets the type of the file as zip.
Here is what I am trying to do:
Get a VBScript to run another VBScript.
get the second VBScript to post an error on completion, either 0 if successful or >0 if not back to the original script and then work on conditions Based on the error code returned.
Uninstall 2010 & copy office 2013
'Copy files from a network share to machine
Set FSO = CreateObject("Scripting.FileSystemObject")
WScript.Echo "Starting to uninstall Microsoft Office 2010 from the machine"
FSO.CopyFile "\\data01\Tools\WSM\Copy_2013.vbs", "C:\temp\Copy_2013.vbs"
FSO.CopyFile "\\data01\Tools\WSM\OffScrub10.vbs", "C:\Temp\OffScrub10.vbs"
FSO.CopyFile "\\data01\Tools\WSM\DeleteOffice13Package.vbs", "C:\temp\DeleteOffice13Package.vbs"
'Wait to execute rest of script where copied filed need to be in location
WScript.Sleep 5000
'Executes Office 2013 copy at the same time, do not wait to continue uninstalling office 2010
Set objShell = WScript.CreateObject("WScript.Shell")
Call objShell.Run("C:\temp\Copy_2013.vbs", 0, False)
WScript.Sleep 3000
'Run VBScript that uninstalls office 2010 (currently set to copy a non existent path for error capture test)
strRemoveOffice10 = "c:\Temp\offscrub10.vbs ALL /Quiet /NoCancel"
Call objShell.Run(strRemoveOffice10, 0, True)
WScript.Echo Err.Number
If Err.Number <> 0 Then WScript.Echo " Microsoft Office 2010 could not be uninstalled. Please uninstall again manually."
If Err.Number = 0 Then WScript.Echo "Microsoft Office 2010 has uninstalled from the machine"
Set objFileSys = Nothing
WScript.Quit
OffScrub10.vbs
Dim objFileSys
Set objFileSys = CreateObject("Scripting.FileSystemObject")
objFileSys.GetFolder("C:\Temp\Temp1\bla").Copy "C:\WSM\Test"
On Error Resume Next
If Err.Number <> 0 WScript.Quit Err
To enable error handling you need to put On Error Resume Next before the statement that may cause an error. Then you can return a status code like this:
Set fso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
fso.GetFolder("C:\Temp\Temp1\bla").Copy "C:\WSM\Test"
WScript.Quit Err.Number
However, since you said you want a return value >0 in case of an error and Err.Number is an unsigned integer that might be interpreted as a positive or negative value depending on its actual value, something like this might be a better choice:
Set fso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
fso.GetFolder("C:\Temp\Temp1\bla").Copy "C:\WSM\Test"
If Err Then WScript.Quit 1
WScript.Quit 0 'can be omitted, because it's the default
To check the returned value in the calling script you need to capture it in a variable. When using the Call statement like you do in your first script the return value is simply discarded. VBScript does not put return values of external commands in the Err object. You may also want to make sure that your script is being run with cscript.exe to avoid messages/popups blocking execution.
strRemoveOffice10 = "cscript.exe c:\Temp\offscrub10.vbs ALL /Quiet /NoCancel"
rc = objShell.Run(strRemoveOffice10, 0, True)
If rc = 0 Then
'OK
Else
'an error occurred
End If
Yes, you can return an exit code from your second script to the first as follows...
WScript.Quit(-1)
Where -1 is your exit code of choice.
Option Explicit
If WScript.Arguments.Count = 0 Then
' If we don't have any arguments, call ourselves to retrieve
' the exit code. It will be returned by the call to the
' Run method
Dim returnCode
returnCode = WScript.CreateObject("WScript.Shell").Run ( _
Chr(34) & WScript.ScriptFullName & Chr(34) & " myArgument " _
, 0 _
, True _
)
' Note ^ the "True"
' We need to wait for the "subprocess" to end to retrieve the exit code
Call WScript.Echo(CStr( returnCode ))
Else
' We have arguments, leave current process with exit code
Call WScript.Quit( 1234 )
End If
Quick sample for testing.
There are two elements to consider:
The called subprocess uses the WScript.Quit method to return the process exit code to the caller
The caller must wait for the subprocess to end to retrieve the exit code. The Run method will return the exit code of the subprocess
Hard to make a concise title, but basically, I have started an instance of command prompt from VBS to run an exe, everything works great and I verify my feedback with msgboxes of output line. When the command prompt gets to a part that is loading and says Verifying File (XX%), the VBS does not run anymore. It does not crash, it simply never moves on from its line. I even have noticed that if I don't constantly Writeline, it will pause before that. So while I wait, I constantly write a 1. I dont see anywhere it could be in an infinite loop without showing me a messagebox.
Please help.
set shell = WScript.CreateObject("WScript.Shell")
set oExec = Shell.exec("cmd.exe")
do while Not oExec.StdOut.AtEndOfStream
junkChar = oExec.stdOut.Read(1)
message = message & junkChar
'errormsg = oExec.stderr.readline
if asc(junkChar) = 13 and message <> junkChar then
msgbox message '& len(message)
message = ""
end if
if right(message,1) = ">" and not bool1stCmd then
'msgbox(message)
msgbox("Command" & cmdArchive)
oExec.stdIn.Writeline cmdArchive
bool1stCmd = True
'oExec.StdIn.Write VbCrLf
elseif bool1stCmd then
if InStr(1,message,"Enter a command>")>0 then
msgbox "Enter a command!"
end if
oExec.stdIn.writeline "1"
end if
msgbox "Loop again!"
Loop
msgbox "exiting loop"
I am writing a VB Script to update some files on the network. Before beginning, I want to know if any of the files are locked. I'd like to do this before I actually do any updates.
I am aware that I can handle the error if the file is locked when I try to replace it, but I really want to know if any files are locked before I start updating any files.
Is there any way to see that a file is locked using VBS (apart from trying to replace it)?
This function determines whether a file of interest can be accessed in 'write' mode. This is not exactly the same as determining whether a file is locked by a process. Still, you may find that it works for your situation. (At least until something better comes along.)
This function will indicate that 'write' access is not possible when a file is locked by another process. However, it cannot distinguish that condition from other conditions that prevent 'write' access. For instance, 'write' access is also not possible if a file has its read-only bit set or possesses restrictive NTFS permissions. All of these conditions will result in 'permission denied' when a 'write' access attempt is made.
Also note that if a file is locked by another process, the answer returned by this function is reliable only at the moment the function is executed. So, concurrency problems are possible.
An exception is thrown if any of these conditions are found: 'file not found', 'path not found', or 'illegal file name' ('bad file name or number').
Function IsWriteAccessible(sFilePath)
' Strategy: Attempt to open the specified file in 'append' mode.
' Does not appear to change the 'modified' date on the file.
' Works with binary files as well as text files.
' Only 'ForAppending' is needed here. Define these constants
' outside of this function if you need them elsewhere in
' your source file.
Const ForReading = 1, ForWriting = 2, ForAppending = 8
IsWriteAccessible = False
Dim oFso : Set oFso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Dim nErr : nErr = 0
Dim sDesc : sDesc = ""
Dim oFile : Set oFile = oFso.OpenTextFile(sFilePath, ForAppending)
If Err.Number = 0 Then
oFile.Close
If Err Then
nErr = Err.Number
sDesc = Err.Description
Else
IsWriteAccessible = True
End if
Else
Select Case Err.Number
Case 70
' Permission denied because:
' - file is open by another process
' - read-only bit is set on file, *or*
' - NTFS Access Control List settings (ACLs) on file
' prevents access
Case Else
' 52 - Bad file name or number
' 53 - File not found
' 76 - Path not found
nErr = Err.Number
sDesc = Err.Description
End Select
End If
' The following two statements are superfluous. The VB6 garbage
' collector will free 'oFile' and 'oFso' when this function completes
' and they go out of scope. See Eric Lippert's article for more:
' http://blogs.msdn.com/b/ericlippert/archive/2004/04/28/when-are-you-required-to-set-objects-to-nothing.aspx
'Set oFile = Nothing
'Set oFso = Nothing
On Error GoTo 0
If nErr Then
Err.Raise nErr, , sDesc
End If
End Function
The script below tries to write to a file for 30 seconds and gives up after that. I needed this when all our users had to click on a script. Chances are that multiple users try to write at the same time. OpenCSV() tries to open the file 30 times with a delay of 1 second in between.
Const ForAppending = 8
currentDate = Year(Now) & "-" & Month(Now) & "-" & Day(Now) & " " & Hour(Now) & ":" & Minute(Now) & ":" & Second(Now)
filepath = "\\network\path\file.csv"
Set oCSV = OpenCSV( filepath )
oCSV.WriteLine( currentDate )
oCSV.Close
Function OpenCSV( path )
Set oFS = CreateObject( "Scripting.FileSystemObject" )
For i = 0 To 30
On Error Resume Next
Set oFile = oFS.OpenTextFile( path, ForAppending, True )
If Not Err.Number = 70 Then
Set OpenCSV = oFile
Exit For
End If
On Error Goto 0
Wscript.Sleep 1000
Next
Set oFS = Nothing
Set oFile = Nothing
If Err.Number = 70 Then
MsgBox "File " & filepath & " is locked and timeout was exceeded.", vbCritical
WScript.Quit
End If
End Function
Or, more simply:
Assuming you already have a variable in your VBS named FileName, which contains the full filepath you want to test:
Dim oFso, oFile
Set oFso = CreateObject("Scripting.FileSystemObject")
Set oFile = oFso.OpenTextFile(FileName, 8, True)
If Err.Number = 0 Then oFile.Close
Line 3 tries to open the file you want to test with append permissions enabled. e.g. it attempts to open the file with a write lock.
If opening the file with a write lock generates an error, then your VBS will error on the third line and not continue. At that point your error handling from wherever you called the VBS should kick in. The error message will be "Permission Denied" if you couldn't get a write lock.
If opening the file with a lock doesn't result in an error, then line 4 closes it again. You can now open the file or do whatever you want with it, confident that it doesn't have a write lock on it.
I've written a small VBScript to creates a .zip file and then copies the contents of a specified folder into that .zip file.
I copy the files over one by one for a reason (I know I can do the whole lot at once). However my problem is when I try to copy them one by one without a WScript.Sleep between each loop iteration I get a "File not found or no read permission." error; if I place a WScript.Sleep 200 after each write it works but not 100% of the time.
Pretty much I'd like to get rid of the Sleep function and not rely on that because depending on the file size it may take longer to write therefore 200 milliseconds may not be enough etc.
As you can see with the small piece of code below, I loop through the files, then if they match the extension I place them into the .zip (zipFile)
For Each file In folderToZip.Items
For Each extension In fileExtensions
if (InStr(file, extension)) Then
zipFile.CopyHere(file)
WScript.Sleep 200
Exit For
End If
Next
Next
Any suggestions on how I can stop relying on the Sleep function?
Thanks
This is how we do it in VB6. After calling CopyHere on the zip we wait for async compression to complete like this
Call Sleep(100)
Do
Do While Not pvCanOpenExclusive(sZipFile)
Call Sleep(100)
Loop
Call Sleep(100)
Loop While Not pvCanOpenExclusive(sZipFile)
where the helper function looks like this
Private Function pvCanOpenExclusive(sFile As String) As Boolean
Dim nFile As Integer
nFile = FreeFile
On Error GoTo QH
Open sFile For Binary Access Read Lock Write As nFile
Close nFile
pvCanOpenExclusive = True
QH:
End Function
Nice side-effect is that even if zipping fails this will not end up in infinite loop.
The trouble comes when accessing the zip-file when it's closed by zipfldr.dll, that is when pvCanOpenExclusive returns true.
You are correct, CopyHere is asynchronous.
When I do this in a vbscript, I sleep until the count of files in the zip, is greater than or equal to the count of files copied in.
Sub NewZip(pathToZipFile)
WScript.Echo "Newing up a zip file (" & pathToZipFile & ") "
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim file
Set file = fso.CreateTextFile(pathToZipFile)
file.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)
file.Close
Set fso = Nothing
Set file = Nothing
WScript.Sleep 500
End Sub
Sub CreateZip(pathToZipFile, dirToZip)
WScript.Echo "Creating zip (" & pathToZipFile & ") from (" & dirToZip & ")"
Dim fso
Set fso= Wscript.CreateObject("Scripting.FileSystemObject")
If fso.FileExists(pathToZipFile) Then
WScript.Echo "That zip file already exists - deleting it."
fso.DeleteFile pathToZipFile
End If
If Not fso.FolderExists(dirToZip) Then
WScript.Echo "The directory to zip does not exist."
Exit Sub
End If
NewZip pathToZipFile
dim sa
set sa = CreateObject("Shell.Application")
Dim zip
Set zip = sa.NameSpace(pathToZipFile)
WScript.Echo "opening dir (" & dirToZip & ")"
Dim d
Set d = sa.NameSpace(dirToZip)
' for diagnostic purposes only
For Each s In d.items
WScript.Echo s
Next
' http://msdn.microsoft.com/en-us/library/bb787866(VS.85).aspx
' ===============================================================
' 4 = do not display a progress box
' 16 = Respond with "Yes to All" for any dialog box that is displayed.
' 128 = Perform the operation on files only if a wildcard file name (*.*) is specified.
' 256 = Display a progress dialog box but do not show the file names.
' 2048 = Version 4.71. Do not copy the security attributes of the file.
' 4096 = Only operate in the local directory. Don't operate recursively into subdirectories.
WScript.Echo "copying files..."
zip.CopyHere d.items, 4
Do Until d.Items.Count <= zip.Items.Count
Wscript.Sleep(200)
Loop
End Sub
You can try accessing the file you've just copied, for example with an "exists" check:
For Each file In folderToZip.Items
For Each extension In fileExtensions
If LCase(oFSo.GetExtensionName(file)) = LCase(extension) Then
zipFile.CopyHere(file)
Dim i: i = 0
Dim target: target = oFSO.BuildPath(zipFile, oFSO.GetFileName(file))
While i < 100 And Not oFSO.FileExists(target)
i = i + 1
WScript.Sleep 10
Wend
Exit For
End If
Next
Next
I'm not sure if target is calculated correctly for this use context, but you get the idea. I'm a bit surprised that this error occurs in the first place... FileSystemObject should be strictly synchronous.
If all else fails, do this:
For Each file In folderToZip.Items
For Each extension In fileExtensions
If LCase(oFSo.GetExtensionName(file)) = LCase(extension) Then
CompressFailsafe zipFile, file
Exit For
End If
Next
Next
Sub CompressFailsafe(zipFile, file)
Dim i: i = 0
Const MAX = 100
On Error Resume Next
While i < MAX
zipFile.CopyHere(file)
If Err.Number = 0 Then
i = MAX
ElseIf Err.Number = xxx ''# use the actual error number!
Err.Clear
WScript.Sleep 100
i = i + 1
Else
''# react to unexpected error
End Of
Wend
On Error GoTo 0
End Sub
The solution we used after much debugging and QA on various windows flavours, including fast and slow machines and machines under heavy CPU load was the following snippet.
Critique and improvements welcome.
We were not able to find a way of doing this without a loop, that is, if you wanted to do some validation or post zipping work.
The goal was to build something that ran reliably on as many windows flavours as possible. Ideally as natively as possible too.
Be advised that this code is still is NOT 100% reliable but its seems to be ~99%. As stable as we could get it with the dev and QA time available.
Its possible that increasing iSleepTime could make it 100%
Points of note:
The unconditional sleep seems to be the most reliable and compatible approach we found
The iSleepTime should not be reduced, it seems the more frequently the loop runs, the higher the probability of an error, seemingly related to the internal operations of the zip/copy process
iFiles is the source file count
The more simplistic the loop was, the better, for example outputting oZippp.Items().Count in the loop caused inexplicable errors that looked like they could be related to file access/sharing/locking violations. We didn't spend time tracing to find out.
It seems on Windows 7 anyway, that the internals of the zipping process use a temp file located in the cwd of the compressed zip folder, you can see this during long running zips by refreshing your explorer window or listing dir with cmd
We had success with this code on Windows 2000, XP, 2003, Vista, 7
You'd probably want to add a timeout in the loop, to avoid infinite loops
'Copy the files to the compressed folder
oZippp.CopyHere oFolder.Items()
iSleeps = 0
iSleepTime = 5
On Error Resume Next
Do
iSleeps = iSleeps + 1
wScript.Sleep (iSleepTime * 1000)
Loop Until oZippp.Items().Count = iFiles
On Error GoTo 0
If iFiles <> oZippp.Items().Count Then
' some action to handle this error case
Else
' some action to handle success
End If
Here is a trick I used in VB; get the length of the zip file before the change and wait for it to change - then wait another second or two. I only needed two specific files but you could make a loop out of this.
Dim s As String
Dim F As Object 'Shell32.Folder
Dim h As Object 'Shell32.Folder
Dim g As Object 'Shell32.Folder
Dim Flen As Long, cntr As Long, TimerInt As Long
Err.Clear
s = "F:\.zip"
NewZipFolder s
Flen = FileLen(s)
Set F = CreateObject("Shell.Application").namespace(CVar(s))
TimerInt = FileLen("F:\MyBigFile.txt") / 100000000 'set the loop longer for bigger files
F.CopyHere "F:\DataSk\DemoData2010\Test.mdf"
Do
cntr = Timer + TimerInt
Do
DoEvents: DoEvents
Loop While cntr > Timer
Debug.Print Flen
Loop While Flen = FileLen(s)
cntr = Timer + (TimerInt / 2)
Do
DoEvents: DoEvents
Loop While cntr > Timer
Set F = Nothing
Set F = CreateObject("Shell.Application").namespace(CVar(s))
F.CopyHere "F:\MynextFile.txt"
MsgBox "Done!"