1

Occasionally I have this message in the regular screen output of one of my runs via a CMD script:

"The process cannot access the file because it is being used by another process."

I know I can use programs to actively monitor on processes locking files, but this script runs in a background. Also: the locks do exist, but all for a very short time ( < 1 second ).

When I look at the log file that is created by such a run, I can see the error message (as displayed above). I also have the timing, but because of limited output by the script, there is no more info.

So my question is : how do you retroactively find out which file was locked, based on this information ?

It would have been so nice if the error message in question would display the name of the file it finds being locked.

3
  • With built-in Windows tools I fear you can't. But you could try with FileMon...
    – aschipfl
    Commented May 7, 2019 at 15:27
  • I'm afraid as well. It should be in the Event Manager .. Filemon is no longer available for download, MS says the functionality is included in ProcMon. I'll check out the logging functionality of ProcMon.
    – tee
    Commented May 8, 2019 at 8:29
  • Ah, yes, they combined several logging tools into one, seems I forgot about that, sorry...
    – aschipfl
    Commented May 8, 2019 at 8:33

2 Answers 2

0

The question is of importance, since "The process cannot access the file because it is being used by another process." denotes that data integrity was lost.

Most likely the cause are glitches within the CMD script itself. Keep in mind that in terms of CMD any (...) is not a means to lexically structure the script, but implicetely calls an additional CMD-instance! The same applies for call :Label ... goto :EOF subroutines. This is to be undestood as: concurrent processes are launched. At least on a multicore machine, it also means, that those CMD-instances are not executed exactly aligned in the sequential order of the controlling batch script. In particular this concerns their output to the file system. Even if the batch script processor waits for the return of an additional CMD-instance, apparantly it doesn't know, when output to a file is written effectively and the respective file being released. Possibly the batch script processor keeps the file open on intention to speed up consecutive append operations, but fails to always guess appropriately which CMD-instance would become the next writer. A mechanism to explictely flush the write buffer and release the file isn't given.

  • "The process cannot access ..." warnings most likely refer to write operations, only. Any test for accessibilty by utilizing a read operation won't help.
  • As the warnings denote that the file of concern is written incompletely AND the written lines are not in the intended order, the answer to the original question is:

To retroactively find out which file was locked, each write-operation must be logged proactively with hints which file was intended to write to AND written lines should be tagged with some index that hints the intended writing order. By something like

set bFile=locktest.B.txt
del /Q %bFile%
for /L %%i in (0,1,%cBMax%) do @(
    echo { %tFile%
    echo echo !TIME! B_%%i 
    echo !TIME! B_%%i 1>>%tFile%
    echo } %tFile%
)>>%bFile% 2>&1

and you get it [if you ask for DRY, compare "pipelining" below].

Unfortunately the file of concern could be the logfile, that would suffer incompleteness regarding the very point we are interested in. Whereas we rely on the logfile, as we are confronted with a non-deterministic runtime problem that we cannot terminatorily investigate in the console. Thus, we can conlude that the real questions are:

  • How to avoid write-collisions?

  • How to catch a "The process cannot access ..." warning?

We could pipeline through a filter that searches for the warning by text processing. Don't do more than:

@ 2>&1 (...)|for /F "tokens=1*" %%t in ('more') do @if "%%t"=="The" echo !TIME! %%t %%u 

It shows that pipelining breaks the delayed variable expansion, thus we can't do more with it than to transform the warning, that we want to catch, into a fatal (breaking) error by something like goto :EOF, or to parrot the warning itself. Nevertheless, at this point you might be sure that you try to write to %tFile%, that you know without any need for delayed variable expansions from the environment. Thus, without the loss of data integrity in mind, an answer to the original question is:

@ 2>&1 (...)|for /F "tokens=1" %%t in ('more') do @if "%%t"=="The" echo %~n0[B]: cannot append to %tFile% 
-1

I recently had this error happen at the cmd prompt in Windows 10 v1903. The error is displayed in the console for a specific file name which is ZeroBytes.lst. I'm piping text output to this filename on a Ram disk created by ImDisk. Piping this output to any other drive and/or folder(same ramdisk) displays no error. Additionally, the process displays this error immediately but continues to run and completes with errorlevel = 0 when it should set errorlevel GTR 0. In short, the process itself only displays the error but sets no error. It happens when I pipe the output using > R:\WDr\ZeroBytes.lst. Any other filename works without error in R:\WDr and ZeroBytes.lst works without error on any other folder in the R: drive.

I have implemented the work-a-round as follows " >R:\WDr\ZeroBytes.lst 2>&1"

It seemed you were looking for details so hopefully this helps.

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .