PayrollManagementSystem/scripts/windows/Manage-PayrollTasks.ps1

64 lines
4.1 KiB
PowerShell
Raw Normal View History

[CmdletBinding(SupportsShouldProcess = $true)]
param(
[Parameter(Mandatory = $true)][ValidateSet('Check', 'Start', 'Stop')][string]$Action,
[Parameter(Mandatory = $true)][string]$RuntimeDirectory,
[switch]$Apply,
[switch]$Force,
[ValidateRange(0, 600)][int]$GraceSeconds = 30
)
. (Join-Path $PSScriptRoot 'TaskHost.Common.ps1')
$runtime = [IO.Path]::GetFullPath($RuntimeDirectory)
$manifest = Join-Path $runtime 'task-manifest.json'
if (-not (Test-Path -LiteralPath $manifest -PathType Leaf)) { throw '未找到项目安装清单,拒绝管理其他任务。' }
$saved = Get-Content -LiteralPath $manifest -Raw | ConvertFrom-Json
if (-not $saved.PSObject.Properties['ServiceSid'] -or -not $saved.PSObject.Properties['LogonType']) {
throw '安装清单缺少账号核验信息,请管理员核对后重新准备安装。'
}
$plan = Get-PayrollTaskPlan -ProjectRoot $saved.ProjectRoot -PythonPath $saved.PythonPath -RuntimeDirectory $runtime `
-ConnectionFile $saved.ConnectionFile -TaskPath $saved.TaskPath -ApiPort $saved.ApiPort
$tasks = foreach ($expected in $plan.Tasks) {
$actual = Get-ScheduledTask -TaskPath $plan.TaskPath -TaskName $expected.Name -ErrorAction Stop
Assert-PayrollTaskPrincipal -Actual $actual.Principal -Expected $saved
if (@($actual.Actions).Count -ne 1 -or $actual.Actions[0].Execute -ne $expected.Execute -or
$actual.Actions[0].Arguments -ne $expected.Arguments -or $actual.Actions[0].WorkingDirectory -ne $expected.WorkingDirectory) {
throw '任务动作与项目清单不一致,拒绝启动或停止。'
}
$info = Get-ScheduledTaskInfo -TaskPath $plan.TaskPath -TaskName $expected.Name
[pscustomobject]@{ Name = $expected.Name; State = [string]$actual.State;
LastTaskResult = $info.LastTaskResult; LastRunTime = $info.LastRunTime; NextRunTime = $info.NextRunTime;
SettingsValid = ($actual.Settings.MultipleInstances -eq 'IgnoreNew' -and $actual.Settings.RestartCount -eq 3 -and
$actual.Settings.RestartInterval -eq 'PT1M' -and $actual.Settings.ExecutionTimeLimit -eq 'PT0S') }
}
if ($Action -eq 'Check') {
[pscustomobject]@{ TaskPath = $plan.TaskPath; StopRequested = (Test-Path -LiteralPath $plan.StopFile); Tasks = @($tasks) } | ConvertTo-Json -Depth 4
if (@($tasks | Where-Object { -not $_.SettingsValid }).Count) { exit 1 }
exit 0
}
if (-not $Apply -or -not $PSCmdlet.ShouldProcess($plan.TaskPath, $Action)) {
[pscustomobject]@{ Preview = $true; Action = $Action; TaskPath = $plan.TaskPath; Names = @($tasks.Name) } | ConvertTo-Json
return
}
if (@($tasks | Where-Object { -not $_.SettingsValid }).Count) { throw '任务恢复设置不符合交付约定,拒绝改变运行状态。' }
if ($Action -eq 'Start') {
Assert-PayrollHostAccess -Plan $plan -ServiceSid $saved.ServiceSid
if (Test-Path -LiteralPath $plan.StopFile) { Remove-Item -LiteralPath $plan.StopFile }
foreach ($task in $tasks) { Enable-ScheduledTask -TaskPath $plan.TaskPath -TaskName $task.Name | Out-Null; Start-ScheduledTask -TaskPath $plan.TaskPath -TaskName $task.Name }
Write-Output '托管任务已启动;是否自动排队仍由T_PLUS_AUTOMATION_ENABLED决定。'
} else {
'运维请求停止领取任务' | Set-Content -LiteralPath $plan.StopFile -Encoding UTF8
foreach ($task in $tasks) { Disable-ScheduledTask -TaskPath $plan.TaskPath -TaskName $task.Name | Out-Null }
$deadline = (Get-Date).AddSeconds($GraceSeconds)
do {
$running = @($tasks | Where-Object { (Get-ScheduledTask -TaskPath $plan.TaskPath -TaskName $_.Name).State -eq 'Running' })
if (-not $running.Count) { break }
Start-Sleep -Seconds 1
} while ((Get-Date) -lt $deadline)
if ($running.Count -and $Force) {
foreach ($task in $running) { Stop-ScheduledTask -TaskPath $plan.TaskPath -TaskName $task.Name }
Write-Output '已强制停止明确的项目任务;未结束的采集需在重启后人工核对中断记录。'
} elseif ($running.Count) {
Write-Output '已停止领取新任务,现有长采集尚在退出;未强制终止,可稍后Check。'
exit 2
} else { Write-Output '项目托管任务已停止。' }
}