PayrollManagementSystem/scripts/windows/Install-PayrollTasks.ps1

67 lines
4.0 KiB
PowerShell
Raw Normal View History

[CmdletBinding(SupportsShouldProcess = $true)]
param(
[Parameter(Mandatory = $true)][string]$ProjectRoot,
[Parameter(Mandatory = $true)][string]$PythonPath,
[Parameter(Mandatory = $true)][string]$RuntimeDirectory,
[Parameter(Mandatory = $true)][string]$ConnectionFile,
[string]$TaskPath = '\PayrollManagementSystem\',
[string]$ServiceAccount,
[int]$ApiPort = 8000,
[switch]$Apply,
[switch]$TestMode
)
. (Join-Path $PSScriptRoot 'TaskHost.Common.ps1')
$plan = Get-PayrollTaskPlan -ProjectRoot $ProjectRoot -PythonPath $PythonPath -RuntimeDirectory $RuntimeDirectory `
-ConnectionFile $ConnectionFile -TaskPath $TaskPath -ApiPort $ApiPort
if ($TestMode -and $TaskPath -notmatch '-Test-[0-9a-f]{8}\\$') { throw '测试模式必须使用独立测试任务目录。' }
if (-not $Apply -or -not $PSCmdlet.ShouldProcess($TaskPath, '注册默认禁用的三个项目托管任务')) {
$plan | ConvertTo-Json -Depth 5
return
}
foreach ($task in $plan.Tasks) {
if (Get-ScheduledTask -TaskPath $TaskPath -TaskName $task.Name -ErrorAction SilentlyContinue) { throw '任务已存在,拒绝覆盖;请先核对当前安装。' }
}
if ($TestMode) {
$account = [Security.Principal.WindowsIdentity]::GetCurrent().Name
$principal = New-ScheduledTaskPrincipal -UserId $account -LogonType Interactive -RunLevel Limited
$credential = $null
} else {
Assert-TaskValue $ServiceAccount
if ($ServiceAccount -match '^(SYSTEM|LocalSystem|NT AUTHORITY\\SYSTEM)$') { throw '请使用已有受限服务账号,不使用SYSTEM。' }
$credential = Get-Credential -UserName $ServiceAccount -Message '请输入已有受限服务账号的凭据(不会写入命令行或清单)'
if ($null -eq $credential) { throw '未提供服务账号凭据,未注册任务。' }
$account = $credential.UserName
$principal = New-ScheduledTaskPrincipal -UserId $account -LogonType Password -RunLevel Limited
}
$serviceSid = Resolve-PayrollAccountSid $account
if ($serviceSid -eq 'S-1-5-18') { throw '请使用已有受限服务账号,不使用SYSTEM。' }
$plan | Add-Member -NotePropertyName ServiceSid -NotePropertyValue $serviceSid
$plan | Add-Member -NotePropertyName LogonType -NotePropertyValue ([string]$principal.LogonType)
Assert-PayrollHostAccess -Plan $plan -ServiceSid $serviceSid
if (Test-Path -LiteralPath (Join-Path $plan.RuntimeDirectory 'task-manifest.json')) { throw '运行目录已有安装清单,拒绝覆盖。' }
'任务已安装但未启用' | Set-Content -LiteralPath $plan.StopFile -Encoding UTF8
$registered = @()
try {
foreach ($task in $plan.Tasks) {
$action = New-ScheduledTaskAction -Execute $task.Execute -Argument $task.Arguments -WorkingDirectory $task.WorkingDirectory
$triggers = @(New-ScheduledTaskTrigger -AtStartup)
if ($task.Role -eq 'maintenance') {
$triggers += New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) -RepetitionInterval (New-TimeSpan -Minutes 1)
}
$definition = New-ScheduledTask -Action $action -Trigger $triggers -Settings (Get-PayrollTaskSettings) -Principal $principal
if ($TestMode) {
Register-ScheduledTask -TaskPath $TaskPath -TaskName $task.Name -InputObject $definition | Out-Null
} else {
$secretPassword = $credential.GetNetworkCredential().Password
try { Register-ScheduledTask -TaskPath $TaskPath -TaskName $task.Name -InputObject $definition -User $account -Password $secretPassword | Out-Null }
finally { $secretPassword = $null }
}
$registered += $task.Name
}
$plan | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $plan.RuntimeDirectory 'task-manifest.json') -Encoding UTF8
Write-Output '三个任务已注册且默认禁用;检查配置后显式执行Start。自动采集开关仍由应用配置控制。'
} catch {
Write-Error ('安装未完成,已注册的任务保持禁用:' + ($registered -join ', ') + '。请核对项目任务目录。')
throw
}