PowerShell ScheduledJob脚本块无法触发恢复挂起的Workflow问题
我手动创建了一个挂起的PowerShell Workflow:
workflow workflowtest1 { Get-Service | Export-Csv C:\temp\workflow-before.txt -NoTypeInformation Suspend-Workflow Get-Service | Export-Csv C:\temp\workflow-after.txt -NoTypeInformation } workflowtest1 -JobName workflowtest1
手动执行Get-Job | Resume-Job可正常恢复该Workflow,但尝试通过ScheduledJob触发恢复时:
$Trigger = New-JobTrigger -Once -At (Get-Date).AddSeconds(30) Register-ScheduledJob -Name WorkScheduledJob ` -Trigger $Trigger ` -ScriptBlock {Import-Module PSWorkflow; Get-Job -Name workflowtest1 | Resume-Job}
ScheduledJob虽成功触发,但Workflow仍处于挂起状态。测试-ScriptBlock {New-Item C:\temp\new_file.txt -Type File}可正常执行。调整为指定凭据的简化命令后,问题依旧:
$adm = "someadminuser1" $pwd = ConvertTo-SecureString -String "somepassword" -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential($adm, $pwd) $Trigger = New-JobTrigger -Once -At (Get-Date).AddSeconds(30) Register-ScheduledJob -Name WorkScheduledJob ` -Trigger $Trigger ` -ScriptBlock {Resume-Job -Name workflowtest1}
原因分析
PowerShell作业(包括Workflow作业)默认是会话隔离的:每个PowerShell会话只能识别自身创建的、或已持久化到磁盘的作业。ScheduledJob运行在独立的后台会话中,无法访问交互式会话里仅存于内存的Workflow作业,因此脚本块中的Resume-Job实际找不到目标作业,自然无法完成恢复操作。
解决方案
1. 让Workflow作业持久化到磁盘
创建Workflow作业时添加-Persist参数,将作业数据保存到磁盘,实现跨会话访问:
# 创建持久化的Workflow作业 workflowtest1 -JobName workflowtest1 -Persist
2. 在ScheduledJob中指定获取持久化Workflow作业
修改ScheduledJob的脚本块,使用Get-PSWorkflowJob(专门针对持久化Workflow作业的命令)定位目标作业后恢复:
$Trigger = New-JobTrigger -Once -At (Get-Date).AddSeconds(30) Register-ScheduledJob -Name WorkScheduledJob ` -Trigger $Trigger ` -ScriptBlock { Import-Module PSWorkflow Get-PSWorkflowJob -Name workflowtest1 | Resume-Job }
3. (可选)通过作业ID精准恢复
如果担心作业名称冲突,可以在创建作业时记录ID,在ScheduledJob中用ID直接定位:
# 创建作业并保存ID $targetJob = workflowtest1 -JobName workflowtest1 -Persist $jobId = $targetJob.Id # 注册带ID参数的ScheduledJob $Trigger = New-JobTrigger -Once -At (Get-Date).AddSeconds(30) Register-ScheduledJob -Name WorkScheduledJob ` -Trigger $Trigger ` -ScriptBlock { Import-Module PSWorkflow Resume-Job -Id $using:jobId }
这里$using:用于将当前会话的$jobId传递到ScheduledJob的独立脚本块中。
权限注意事项
如果ScheduledJob使用了其他用户凭据,需确保该用户有权限访问Workflow作业的默认存储路径:C:\Users\<用户名>\AppData\Local\Microsoft\Windows\PowerShell\Jobs,否则仍无法找到目标作业。
内容的提问来源于stack exchange,提问作者Aziz

