我需要知道,任何企图做任何这样的文件之前。
Answer 1:
Not sure about locked directories (does Windows have that?)
But detecting if a file is being written to by another process is not difficult.
@echo off
2>nul (
>>test.txt echo off
) && (echo file is not locked) || (echo file is locked)
I use the following test script from another window to place a lock on the file.
(
>&2 pause
) >> test.txt
When I run the 2nd script from one window and then run the 1st script from a second window, I get my "locked" message. Once I press <Enter>
in the 1st window, I get the "unlocked" message if I rerun the 1st script.
Explanation
Whenever the output of a command is redirected to a file, the file of course must be opened for write access. The Windows CMD session will attempt to open the file, even if the command does not produce any output.
The >>
redirection operator opens the file in append mode.
So >>test.txt echo off
will attempt to open the file, it writes nothing to the file (assuming echo is already off), and then it closes the file. The file is not modified in any way.
Most processes lock a file whenever they open a file for write access. (There are OS system calls that allow opening a file for writing in a shared mode, but that is not the default). So if another process already has "test.txt" locked for writing, then the redirection will fail with the following error message sent to stderr - "The process cannot access the file because it is being used by another process.". Also an error code will be generated upon redirection failure. If the command and the redirection succeed, then a success code is returned.
Simply adding 2>nul
to the command will not prevent the error message because it redirects the error output for the command, not the redirection. That is why I enclose the command in parentheses and then redirect the error output to nul outside of the parens.
So the error message is effectively hidden, but the error code is still propagated outside of the parens. The standard Windows &&
and ||
operators are used to detect whether the command inside the parens was successful or failed. Presumably echo off
will never fail, so the only possible reason for failure would be the redirection failed. Most likely it fails because of a locking issue, though technically there could be other reasons for failure.
It is a curious "feature" that Windows does not set the %ERRORLEVEL% dynamic variable to an error upon redirection failure unless the ||
operator is used. (See File redirection in Windows and %errorlevel%). So the ||
operator must read the returned error code at some low level, not via the %ERRORLEVEL% variable.
Using these techniques to detect redirection failure can be very useful in a batch context. It can be used to establish locks that allow serialization of multiple events in parallel processes. For example, it can enable multiple processes to safely write to the same log file at the "same" time. How do you have shared log files under Windows?
EDIT
Regarding locked folders. I'm not sure how Windows implements this, perhaps with a lock. But if a process has an active directory involving the folder, then the folder cannot be renamed. That can easily be detected using
2>nul ren folderName folderName && echo Folder is NOT locked || echo folder is LOCKED
EDIT
I have since learned that (call )
(with a space) is a very fast command without side effects that is guaranteed to succeed with ERRORLEVEL set to 0. And (call)
(without a space) is a fast command without side effects that is guaranteed to fail with ERRORLEVEL 1.
So I now use the following to check if a file is locked:
2>nul (
>>test.txt (call )
) && (echo file is not locked) || (echo file is locked)
Answer 2:
除了伟大的答案从dbenham,以下形式终于帮助我理解应用的技术:
( type nul >> file.txt ) 2>nul || echo File is locked!
type nul
命令给出了一个空的输出和不影响当前回波设置像echo off
用原命令。
如果你想使用if–then–else
条件正确顺序的记忆- (成功语句&&
)首先会和(候补声明||
)是怎么回事第二:
command && (echo Command is successful) || (echo Command has failed)
Answer 3:
如果您下载并安装Windows Server 2003 Resource Kit工具有一个叫做程序oh.exe
,将列出打开的文件句柄给定的文件:
http://www.microsoft.com/en-us/download/details.aspx?id=17657
一旦安装后,重新启动计算机,你就可以使用该工具。 你可以看到在帮助和支持中心,以及由输入的所有选项oh /?
在命令提示。
(信息来源: http://windowsxp.mvps.org/processlock.htm )
Answer 4:
注意,一个消息,说明该文件状态的写作比设定的返回码一个批处理命令帮助较小。 例如,如果文件被锁定,返回码1。
@echo off
2>nul (
>>test.tmp echo off
) && (EXIT /B 0) || (EXIT /B 1)
Answer 5:
顺便说一句,dbenham的解决方案似乎也找出如果一个进程正在运行的有效途径。 这是我发现下面的应用的最佳解决方案:
start /b "job1.exe >> job1.out"
start /b /wait "job2.exe >> job2.out"
::wait for job1 to finish using dbenham's code to check if job1.out is in use
comparejobs.exe
Answer 6:
只是我想基于@ dbenham的绝招与大家分享我的脚本示例
Check_Locked_Files.bat:这个脚本的描述该脚本可以扫描和检查一组可以修改到脚本文件夹锁定文件; 例如,我所选择的那些组文件夹的要被扫描:
Set Folders=^
^ "%ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup"^
^ "%UserProfile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"^
^ "%ProgramFiles%\Internet Explorer"^
^ "%ProgramFiles%\Skype"^
^ "%ProgramFiles%\TeamViewer"^
^ "%WinDir%\system32\drivers"^
^ "%Temp%"
输出结果是HTML格式的更多可读性。
如果文件被锁定,我们才会显示为红色,否则我们展示它的绿色。
而整个脚本是:Check_Locked_Files.bat
@echo off
Rem This source is inspired from here
Rem hxxps://stackoverflow.com/questions/
Rem 10518151/how-to-check-in-command-line-if-a-given-file-or-directory-is-locked-used-by-any?answertab=active#tab-top
Rem Thanks for dbenham for this nice trick ;)
Mode con cols=90 lines=5 & color 9E
Title Scan and Check for Locked Files by Hackoo 2017
set "LogFile=%~dp0%~n0.html"
(
echo ^<html^>
echo ^<title^> Scan and Check for locked files by Hackoo 2017^</title^>
echo ^<body bgcolor^=#ffdfb7^>
echo ^<center^>^<b^>Log Started on %Date% @ %Time% by the user : "%username%" on the computer : "%ComputerName%"^</b^>^</center^>
)> "%LogFile%"
echo(
echo --------------------------------------------------------------------------
echo Please Wait a while ....... Scanning for locked files is in progress
echo --------------------------------------------------------------------------
Rem We Play radio just for fun and in order to let the user be patient until the scan ended
Call :Play_DJ_Buzz_Radio
Timeout /T 3 /nobreak>nul
cls
Set Folders=^
^ "%ProgramData%\Microsoft\Windows\Start Menu\Programs\Startup"^
^ "%UserProfile%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"^
^ "%ProgramFiles%\Internet Explorer"^
^ "%ProgramFiles%\Skype"^
^ "%ProgramFiles%\TeamViewer"^
^ "%WinDir%\system32\drivers"^
^ "%Temp%"
@For %%a in (%Folders%) Do (
( echo ^<hr^>^<font color^=DarkOrange^>^<B^>Folder : %%a^</B^>^</font^>^<hr^>) >> "%LogFile%"
@for /f "delims=" %%b in ('Dir /A-D /s /b "%%~a\*.*"') do (
Call :Scanning "%%~nxb"
Call:Check_Locked_File "%%~b" "%LogFile%"
)
)
(
echo ^<hr^>
echo ^<center^>^<b^>Log ended on %Date% @ %Time% on the computer : "%ComputerName%"^</b^>^</center^>
echo ^</body^>
echo ^</html^>
)>> "%LogFile%"
Start "" "%LogFile%" & Call :Stop_Radio & exit
::***********************************************************************************
:Check_Locked_File <File> <LogFile>
(
2>nul (
>>%1 (call )
) && ( @echo ^<font color^=green^>file "%~1"^</font^>^<br^>
) || (
@echo ^<font color^=red^>file "%~1" is locked and is in use^</font^>^<br^>
)
)>>%2 2>nul
exit /b
::***********************************************************************************
:Scanning <file>
cls
echo(
echo --------------------------------------------------------------------------
echo Please Wait a while... Scanning for %1
echo --------------------------------------------------------------------------
exit /b
::***********************************************************************************
:Play_DJ_Buzz_Radio
Taskkill /IM "wscript.exe" /F >nul 2>&1
Set "vbsfile=%temp%\DJBuzzRadio.vbs"
Set "URL=http://www.chocradios.ch/djbuzzradio_windows.mp3.asx"
Call:Play "%URL%" "%vbsfile%"
Start "" "%vbsfile%"
Exit /b
::**************************************************************
:Play
(
echo Play "%~1"
echo Sub Play(URL^)
echo Dim Sound
echo Set Sound = CreateObject("WMPlayer.OCX"^)
echo Sound.URL = URL
echo Sound.settings.volume = 100
echo Sound.Controls.play
echo do while Sound.currentmedia.duration = 0
echo wscript.sleep 100
echo loop
echo wscript.sleep (int(Sound.currentmedia.duration^)+1^)*1000
echo End Sub
)>%~2
exit /b
::**************************************************************
:Stop_Radio
Taskkill /IM "wscript.exe" /F >nul 2>&1
If Exist "%vbsfile%" Del "%vbsfile%"
::**************************************************************
Answer 7:
:: Create the file Running.tmp
ECHO %DATE% > Running.tmp
ECHO %TIME% >> Running.tmp
:: block it and do the work
(
>&2 CALL :Work 30
) >> Running.tmp
:: when the work is finished, delete the file
DEL Running.tmp
GOTO EOF
:: put here the work to be done by the batch file
:Work
ping 127.0.0.1 -n 2 -w 1000 > NUL
ping 127.0.0.1 -n %1 -w 1000 > NUL
:: when the process finishes, the execution go back
:: to the line after the CALL
Answer 8:
如果你想在Cygwin的Bash使用此,这里是单行:
# To lock a file: (in a different window)
cmd.exe /C "( >&2 pause ) >> test.txt"
#Press any key to continue . . .
# To test if a file is locked (with text)
cmd.exe /C "2>nul ( >>test.txt (call ) ) && (echo ok) || (echo locked)"
#locked
# To test if a file is locked (with POSIX exit code)
cmd.exe /C "2>nul ( >>test.txt (call ) ) && (exit /b 0) || (exit /b 1)"
echo $?
#1