批处理中判断进程是否运行,运行则退出,防止bat重复运行的bat代码

 更新时间:2026年04月06日 18:56:13   投稿: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分钟的旧锁文件。

相关文章

最新评论