批处理中判断进程是否运行,运行则退出,防止bat重复运行的bat代码
投稿:mdxy-dxy
最近执行一些bat程序,为了防止bat重复运行导致问题,,下面的批处理脚本,用于判断自身(或指定进程)是否已经在运行,如果已在运行则退出
功能:判断自身是否正在运行,如果已经运行,就直接退出,不重复启动。
单文件完整代码(直接复制保存为 .bat 即可)
下面是一个批处理脚本,用于判断自身(或指定进程)是否已经在运行,如果已在运行则退出:
方法一:通过临时文件判断(简单实用)
@echo off
setlocal enabledelayedexpansion
:: ==============================================
:: 功能:判断当前批处理是否正在运行
:: 如果已经运行,则自动退出,不重复启动
:: ==============================================
:: 定义一个唯一锁文件名
set "LOCK_FILE=%temp%\my_batch_running.lock"
:: 判断锁文件是否存在
if exist "%LOCK_FILE%" (
echo 批处理已在运行,自动退出...
pause
exit /b
)
:: 创建锁文件(标记正在运行)
echo running > "%LOCK_FILE%"
:: ==================== 你的业务代码开始 ====================
echo 批处理已启动
echo 正在执行任务...
pause
:: ==================== 你的业务代码结束 ====================
:: 程序结束后删除锁文件
del "%LOCK_FILE%" 2>nul
endlocal核心原理
- 启动时创建一个临时锁文件
- 再次运行时,检测到锁文件存在 → 直接退出
- 正常关闭时自动删除锁文件,不影响下次启动
如果你想要【完全静默、不弹窗】版本
@echo off set "LOCK_FILE=%temp%\my_batch_running.lock" if exist "%LOCK_FILE%" exit /b echo running > "%LOCK_FILE%" :: 你的代码 del "%LOCK_FILE%" 2>nul
比较推荐的一个代码
@echo off
set "lockfile=%temp%\%~nx0.lock"
:: 检查锁文件是否存在
if exist "%lockfile%" (
echo 程序已在运行中,即将退出...
timeout /t 2 >nul
exit /b
)
:: 创建锁文件
echo %date% %time% > "%lockfile%"
:: 正常执行你的脚本内容
echo 脚本开始执行...
pause
:: 脚本结束时删除锁文件
del "%lockfile%" 2>nul需要确认%temp%目录有读取写入权限,主要是服务器中需要注意,也可以换个目录,比较好,比较临时目录很多安全设置软件会禁止。

那么代码就可以这么写
@echo off
set "lockfile=%~dp0\%~nx0.lock"
:: 检查锁文件是否存在
if exist "%lockfile%" (
echo 程序已在运行中,即将退出...
timeout /t 2 >nul
exit /b
)
:: 创建锁文件
echo %date% %time% > "%lockfile%"
:: 正常执行你的脚本内容
echo 脚本开始执行...
pause
:: 脚本结束时删除锁文件
del "%lockfile%" 2>nul方法二:判断自身批处理进程
@echo off
title MyBatchScript
:: 获取当前批处理脚本的进程ID
set "current_pid=%random%"
for /f "tokens=2" %%a in ('tasklist /fi "imagename eq cmd.exe" /nh 2^>nul') do (
echo %%a | findstr /i "%current_pid%" >nul 2>nul || (
:: 检查是否是当前脚本
wmic process where "processid=%%a" get commandline | findstr /i "%~nx0" >nul 2>nul
if !errorlevel! equ 0 (
set /a count+=1
)
)
)
if %count% gtr 1 (
echo 程序已在运行中,即将退出...
timeout /t 2 >nul
exit /b
)
:: 正常执行你的脚本内容
echo 脚本开始执行...
pause方法三:判断特定进程名(如 notepad.exe)
主要针对运行的exe文件名,方便bat调用一些exe文件的时候
@echo off
set "process_name=notepad.exe"
:: 检查进程是否运行
tasklist /fi "imagename eq %process_name%" 2>nul | findstr /i "%process_name%" >nul
if %errorlevel% equ 0 (
echo %process_name% 已在运行中,即将退出...
timeout /t 2 >nul
exit /b
)
:: 正常执行你的脚本内容
echo %process_name% 未运行,继续执行...
start notepad.exe方法四:使用标签和进程列表(推荐用于复杂场景)
@echo off
set "scriptname=%~nx0"
:: 获取当前脚本的进程数
set "count=0"
for /f "skip=3 tokens=1-2" %%a in ('tasklist /fi "imagename eq cmd.exe" /fo table /nh 2^>nul') do (
for /f "tokens=*" %%c in ('wmic process where "processid=%%b" get commandline ^| findstr /i "%scriptname%" 2^>nul') do (
set /a count+=1
)
)
if %count% gtr 1 (
echo 检测到脚本已在运行中,数量:%count%
echo 即将退出...
ping -n 3 127.0.0.1 >nul
exit /b
)
echo 脚本正常运行...
:: 在这里添加你的主要代码
pause注意事项:
方法一(锁文件法)最简单可靠,但如果在脚本运行过程中异常终止,锁文件可能不会被删除
方法二和方法四更精确,但需要 WMIC 支持(Windows 7 及以上系统)
如果使用锁文件法,建议在脚本开头添加清理逻辑:
:: 清理超过24小时的旧锁文件 forfiles /p "%temp%" /m "%~nx0.lock" /d -1 /c "cmd /c del @file" 2>nul
选择最适合你需求的方法即可。对于大多数情况,方法一(锁文件法) 是最简单实用的选择。
清理超过20分钟的旧锁文件
使用 forfiles 清理超过20分钟的旧锁文件,由于 forfiles 的 /d 参数只支持天数,不支持分钟,所以需要换一种方法。以下是几种解决方案:
方法一:使用 forfiles 配合文件时间比较(推荐)
batch
@echo off
set "lockfile=%temp%\%~nx0.lock"
:: 清理超过20分钟的锁文件
forfiles /p "%temp%" /m "%~nx0.lock" /c "cmd /c if @isdir==FALSE (for /f \"tokens=1-6 delims=/: \" %%a in ('echo @fdate @ftime') do (call :CheckTime \"%%a-%%b-%%c %%d:%%e:%%f\"))" 2>nul
:: 或者使用更简单的方法:检查文件修改时间
if exist "%lockfile%" (
for %%a in ("%lockfile%") do (
set "filetime=%%~ta"
set "now=%date% %time%"
REM 这里需要复杂的时间计算,建议使用方法二
)
)
goto :main
:CheckTime
REM 这个方法比较复杂,建议使用下面的方法二
exit /b方法二:使用 PowerShell(最精确)
batch
@echo off
set "lockfile=%temp%\%~nx0.lock"
:: 使用PowerShell检查并删除超过20分钟的锁文件
powershell -Command "& {
$file = '%lockfile%';
if (Test-Path $file) {
$filetime = (Get-Item $file).LastWriteTime;
$agetime = (Get-Date) - $filetime;
if ($agetime.TotalMinutes -gt 20) {
Remove-Item $file -Force;
Write-Host '已删除超过20分钟的锁文件';
}
}
}" 2>nul
:: 检查锁文件是否存在
if exist "%lockfile%" (
echo 程序已在运行中(锁文件存在且未超过20分钟),即将退出...
timeout /t 2 >nul
exit /b
)
:: 创建新锁文件
echo %date% %time% > "%lockfile%"
:main
:: 正常执行你的脚本内容
echo 脚本开始执行...
pause
:: 脚本结束时删除锁文件
del "%lockfile%" 2>nul方法三:使用 VBScript(无需PowerShell)
创建 checklock.vbs 文件:
vbs
' checklock.vbs
Set fso = CreateObject("Scripting.FileSystemObject")
lockfile = WScript.Arguments(0)
If fso.FileExists(lockfile) Then
Set file = fso.GetFile(lockfile)
filetime = file.DateLastModified
ageminutes = DateDiff("n", filetime, Now)
If ageminutes > 20 Then
fso.DeleteFile lockfile, True
WScript.Echo "Deleted old lock file"
WScript.Quit 0 ' 文件已删除,可以继续
Else
WScript.Echo "Lock file is recent, exiting"
WScript.Quit 1 ' 文件存在且未过期
End If
Else
WScript.Quit 0 ' 文件不存在,可以继续
End If在批处理中调用:
batch
@echo off
set "lockfile=%temp%\%~nx0.lock"
:: 调用VBScript检查并清理锁文件
cscript //nologo "%~dp0checklock.vbs" "%lockfile%"
if %errorlevel% equ 1 (
echo 程序已在运行中(锁文件存在且未超过20分钟),即将退出...
timeout /t 2 >nul
exit /b
)
:: 创建新锁文件
echo %date% %time% > "%lockfile%"
:: 正常执行你的脚本内容
echo 脚本开始执行...
pause
:: 脚本结束时删除锁文件
del "%lockfile%" 2>nul方法四:纯批处理实现(无需额外工具)
batch
@echo off
setlocal enabledelayedexpansion
set "lockfile=%temp%\%~nx0.lock"
:: 检查并清理超过20分钟的锁文件
if exist "%lockfile%" (
for /f "tokens=1-2 delims= " %%a in ('dir /tc "%lockfile%" ^| findstr "%lockfile%"') do (
set "filedate=%%a"
set "filetime=%%b"
)
:: 获取当前时间
set "now=%date% %time%"
:: 这里简化处理,实际需要复杂的时间计算
REM 建议使用前面几种方法,纯批处理处理时间差很复杂
REM 作为替代,可以使用临时文件方式
echo 锁文件已存在,但无法精确判断20分钟
echo 如需精确判断,请使用PowerShell或VBScript方法
)
:: 简单方案:检查文件是否超过20分钟(近似)
if exist "%lockfile%" (
for %%a in ("%lockfile%") do set "filetime=%%~ta"
REM 需要复杂的字符串处理,不推荐
)
goto :main推荐方案:使用 PowerShell(最简洁)
batch
@echo off
set "lockfile=%temp%\%~nx0.lock"
:: 使用PowerShell检查和清理(单行命令)
powershell -Command "if (Test-Path '%lockfile%') { $t=(Get-Item '%lockfile%').LastWriteTime; if (((Get-Date)-$t).TotalMinutes -gt 20) { Remove-Item '%lockfile%' -Force } }" 2>nul
:: 检查锁文件是否仍然存在
if exist "%lockfile%" (
echo 程序已在运行中(锁文件存在且未超过20分钟)
echo 如果确认程序未运行,请手动删除文件:%lockfile%
timeout /t 3 >nul
exit /b
)
:: 创建新锁文件
echo %date% %time% - Process ID: !random! > "%lockfile%"
echo 脚本开始执行...
:: 你的主要代码在这里
pause
:: 清理
del "%lockfile%" 2>nul说明:
方法二(PowerShell) 最简单精确,Windows 7及以上系统默认支持
方法三(VBScript) 适合没有PowerShell的环境
纯批处理处理分钟级时间差非常复杂,不推荐
选择 PowerShell 方法即可完美实现清理超过20分钟的旧锁文件。
