Is a File Ready? Waiting for a File Process to Complete.
In the comments to my last post Richard asked how we can wait for a process to finish updating a file.
In my reply to Richard I point out that most of the time we can use a visual cue. Where possible this is the approach I would use. Usually an application would present some kind of visual cue when the file operation finishes. A dialog box might appear, or disappear, an object may become enabled or disabled, some text may appear on the screen, etc. We might be able to use commands such as WaitWindowOpen, WaitWindowClosed, WaitWindowChanged, WaitScreenText, WaitScreenImage, WaitCursorChanged, WaitPixelColor, or WaitRectChanged. Or we might even create our own wait loop which checks for some value or property. I mention this approach in Top Tips for Reliable Macros.
Unfortunately there are sometimes scenarios where there is no visual cue and we have nothing we can “see” which tells us the file operation has completed.
If the file is locked by the application that is writing to it, we could create a wait loop which checks to see if the file is still locked or not.
How might we achieve that? Well, why not just try to read from the file. If the file is locked we’re not going to be able to read it right? So we could just do:
Label>wait_file ReadLn>file,1,res Pos>##ERR##,res,1,pErr If>pErr>0 Wait>0.2 Goto>wait_file Endif
This will work for any kind of file.
Of course this assumes that the file is locked for reading by other processes.
It’s possible that the application locks the file only for writing. In that situation we could use WriteLn to attempt to write an empty string to the file:
Let>WLN_NOCRLF=1 Label>wait_file WriteLn>file,res,{""} If>RES<>0 Wait>0.2 Goto>wait_file Endif
But that’s a bit invasive in the instance that the file IS available as although we’re writing nothing, we’re still modifying it so updating it’s timestamp.
We can get a bit more control over this with VBScript where we can attempt to open a file for appending without actually modifying it:
VBSTART Function TestFile(filename) Set oFSO = CreateObject("Scripting.FileSystemObject") On Error Resume Next Set f = oFSO.OpenTextFile(filename, 8, True) TestFile = Err.Number End Function VBEND Let>file=C:\files\bmp.bmp Label>wait_file VBEval>TestFile("%file%"),fRes If>fRes<>0 Wait>0.2 Goto>wait_file Endif
All the TestFile function does is try to open the file for appending, and if an error occurs it returns the error code. So if we get zero back, there’s no error and the file must be available for writing and therefore not locked.
Don’t be put off by the fact that this uses the OpenTextFile method. It will still work with any kind of file. We’re not actually going to attempt to modify it. We’re just trying to see if we can open it. So the file type is unimportant.
Note that in these samples I haven’t checked for any specific error code nor have I checked for the existence of the file first – I’m assuming any error means the file isn’t available. An error will also be returned if the file does not exist, so you’d probably want to use IfFileExists first. You might even want to put FileExists in a loop so that you can wait until it exists.
Note also the small wait in each loop. This is just to make sure the loop isn’t so tight that it hogs CPU. Better to be nice to the system and give other processes a chance to breathe.