<# .SYNOPSIS 注册 / 移除 BakNRet 的每日备份计划任务。 .DESCRIPTION 任务直接调用 Backup-Data.ps1。脚本自身会写日志并按失败数返回退出码, 因此「上次运行结果」在任务计划程序里是可读的,不需要额外包装。 注册计划任务需要管理员权限(本脚本不自己提权,请从管理员终端运行)。 .EXAMPLE # 先看将要注册什么(只读,不需要管理员) .\tools\Register-BackupTask.ps1 -At '21:30' -DryRun .EXAMPLE .\tools\Register-BackupTask.ps1 -At '21:30' .EXAMPLE .\tools\Register-BackupTask.ps1 -Remove #> [CmdletBinding(SupportsShouldProcess = $true)] param( [string]$TaskName = 'BakNRet Backup', # 每日触发时间,HH:mm [ValidatePattern('^\d{1,2}:\d{2}$')] [string]$At = '21:30', # 额外传给 Backup-Data.ps1 的参数,例如 @('-Snapshot') [string[]]$BackupArgument = @(), [ValidateSet('S4U', 'Interactive')] [string]$LogonType = 'S4U', # 用哪个 PowerShell 宿主执行(默认优先 pwsh.exe) [string]$PowerShellPath, [switch]$Remove, [switch]$DryRun ) $ErrorActionPreference = 'Stop' $projectRoot = Split-Path -Parent $PSScriptRoot $backupScript = Join-Path $projectRoot 'Backup-Data.ps1' if (-not (Test-Path -LiteralPath $backupScript)) { Write-Error "找不到 Backup-Data.ps1:$backupScript" exit 1 } if (-not $PowerShellPath) { $pwsh = Get-Command pwsh.exe -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Source $PowerShellPath = if ($pwsh) { $pwsh } else { (Get-Command powershell.exe -ErrorAction Stop).Source } } $argumentParts = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', "`"$backupScript`"") + $BackupArgument $argument = ($argumentParts -join ' ') Write-Host '' Write-Host "任务名 : $TaskName" Write-Host "执行程序 : $PowerShellPath" Write-Host "参数 : $argument" Write-Host "触发 : 每天 $At" Write-Host "登录类型 : $LogonType(S4U = 未登录也运行,但访问不到网络资源)" Write-Host '' if ($Remove) { if ($DryRun) { Write-Host '[试运行] 将移除计划任务' -ForegroundColor Yellow exit 0 } if (-not (Get-Command Unregister-ScheduledTask -ErrorAction SilentlyContinue)) { Write-Error '当前环境没有计划任务 cmdlet。' exit 1 } try { Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction Stop Write-Host "已移除计划任务:$TaskName" -ForegroundColor Green } catch { Write-Error "移除失败(多半是权限不足,请用管理员终端):$_" exit 1 } exit 0 } if ($DryRun) { Write-Host '[试运行] 未实际注册。去掉 -DryRun 并确保在管理员终端里执行即可注册。' -ForegroundColor Yellow exit 0 } foreach ($cmdlet in 'Register-ScheduledTask', 'New-ScheduledTaskTrigger', 'New-ScheduledTaskAction', 'New-ScheduledTaskSettingsSet', 'New-ScheduledTaskPrincipal') { if (-not (Get-Command $cmdlet -ErrorAction SilentlyContinue)) { Write-Error "当前环境缺少 $cmdlet,无法注册计划任务。" exit 1 } } $action = New-ScheduledTaskAction -Execute $PowerShellPath -Argument $argument -WorkingDirectory $projectRoot $trigger = New-ScheduledTaskTrigger -Daily -At $At $settings = New-ScheduledTaskSettingsSet ` -StartWhenAvailable ` -MultipleInstances IgnoreNew ` -AllowStartIfOnBatteries ` -DontStopIfGoingOnBatteries ` -ExecutionTimeLimit (New-TimeSpan -Hours 6) $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name $principal = New-ScheduledTaskPrincipal -UserId $identity -LogonType $LogonType -RunLevel Highest try { Register-ScheduledTask -TaskName $TaskName -Action $action -Trigger $trigger ` -Settings $settings -Principal $principal -Force -ErrorAction Stop | Out-Null Write-Host "已注册计划任务:$TaskName(每天 $At)" -ForegroundColor Green Write-Host "查看上次运行结果:Get-ScheduledTaskInfo -TaskName '$TaskName'" -ForegroundColor DarkGray Write-Host "手动跑一次验证 :Start-ScheduledTask -TaskName '$TaskName'" -ForegroundColor DarkGray } catch { Write-Error "注册失败(多半是权限不足,请用管理员终端):$_" exit 1 } exit 0