任务计划触发PowerShell脚本时,如何检查前实例是否运行并等待?
PowerShell脚本串行执行方案(避免并行运行)
当你的PowerShell脚本被任务计划程序多次触发时,要实现"前一次未完成则等待"的逻辑,最可靠的方式是使用Windows命名互斥锁(Mutex),它能跨进程实现同步,确保同一时间只有一个脚本实例执行。
核心实现代码
# 生成唯一的互斥锁名称(基于脚本路径的哈希值,避免和其他脚本冲突) $scriptPath = $MyInvocation.MyCommand.Path $mutexName = "ScriptExecutionMutex_$(Get-FileHash -Path $scriptPath -Algorithm MD5 | Select-Object -ExpandProperty Hash)" # 创建互斥锁实例 $mutex = New-Object System.Threading.Mutex($false, $mutexName) try { Write-Host "等待获取执行权限..." # 无限等待直到获取到互斥锁(可根据需求修改超时时间,比如60000=60秒) if ($mutex.WaitOne([System.Threading.Timeout]::Infinite, $false)) { try { # -------------------------- # 这里放置你的脚本核心逻辑 Write-Host "开始执行脚本任务..." # 示例:模拟耗时操作 Start-Sleep -Seconds 30 Write-Host "脚本任务执行完成" # -------------------------- } finally { # 无论执行成功/失败,都必须释放互斥锁 $mutex.ReleaseMutex() } } } catch { Write-Error "获取执行权限时出错: $_" } finally { # 销毁互斥锁资源 $mutex.Dispose() }
关键说明
- 唯一互斥锁名称:通过脚本路径的MD5哈希生成名称,确保每个脚本的互斥锁独立,不会和其他脚本的互斥锁冲突。
- 超时设置:如果不想无限等待,可将
[System.Threading.Timeout]::Infinite替换为具体毫秒数(如60000表示等待60秒),超时后脚本会退出。 - 安全释放:使用
finally块确保互斥锁被释放,避免因脚本异常导致后续实例无法获取权限。
备选方案(不推荐)
如果暂时无法使用互斥锁,也可以通过检查进程的方式实现,但存在局限性:
$scriptName = $MyInvocation.MyCommand.Name # 查找当前脚本的其他运行实例 $runningInstances = Get-Process -Name powershell -ErrorAction SilentlyContinue | Where-Object { $_.CommandLine -match [regex]::Escape($scriptName) -and $_.Id -ne $PID } if ($runningInstances) { Write-Host "检测到脚本已有实例在运行,等待中..." $runningInstances | Wait-Process } # 执行脚本核心逻辑 Write-Host "开始执行脚本..." Start-Sleep -Seconds 30 Write-Host "执行完成"
该方案的缺陷:无法准确区分同名脚本、权限不足时无法读取进程命令行、脚本调用方式变化时匹配失效,仅适合简单场景。
内容的提问来源于stack exchange,提问作者cheppalli abhishek
相关产品推荐
相关产品推荐

