如何在 Powershell 中开始一个比它的父级寿命更长的后台作业?
Posted
技术标签:
【中文标题】如何在 Powershell 中开始一个比它的父级寿命更长的后台作业?【英文标题】:How can I start a background job in Powershell that outlives it's parent? 【发布时间】:2020-02-03 20:57:09 【问题描述】:考虑以下代码:
start-job -scriptblock sleep 10; cmd /c set > c:\env.txt;
exit
当父级退出时后台作业被终止,因此对 cmd.exe 的调用永远不会发生。我想写一些类似的代码,让父立即退出,子继续在后台运行。
如果可能,我希望将所有内容都保存在一个脚本中。
【问题讨论】:
【参考方案1】:你必须开始一个进程:
start-process powershell -ArgumentList "sleep 10; cmd /c set > c:\env.txt" -WindowStyle hidden
【讨论】:
【参考方案2】:如果您使用 Start-Process,您将创建一个以您的 powershell 会话作为其父进程的新子进程。如果您杀死启动它的 powershell 父 进程,新进程将成为孤立进程并继续运行。但是,如果您杀死父进程的进程树
,它将无法生存Start-Process -FilePath notepad.exe
Powershell 无法在其进程树之外为您启动新的独立进程。但是,这可以在 Windows 中使用 CreateProcess 完成,并且此功能通过 WMI 公开。幸运的是,您可以从 powershell 调用它:
Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList notepad.exe
这样,如果 进程树 被杀死,新进程也将继续运行,因为新进程没有您的 powershell 会话作为父进程,而是 WMI 主机进程。
【讨论】:
【参考方案3】:如果发现使用 Invoke-Command 能够绕过后台作业与其父级一起死亡的限制。好在语法几乎和 start-job 一样,所以脚本块可以保持原样。
start-job -scriptblock sleep 10; cmd /c set > c:\env.txt;
会变成
Invoke-Command -ComputerName . -AsJob -scriptblock sleep 10; cmd /c set > c:\env.txt;
突然在它的父级死亡后幸存下来(可能是因为 invoke-command 适合在另一台计算机上运行程序,所以父级永远不会影响它)
【讨论】:
似乎Invoke-Command 需要remote requirements 也用于本地操作。【参考方案4】:你也可以这样做
$a = start-job -scriptblock sleep 10; cmd /c set > c:\env.txt;
Register-ObjectEvent -InputObject $a -EventName StateChanged -SourceIdentifier "finished"
$b = Wait-Event -SourceIdentifier "finished"
exit
您的脚本将等待脚本块结束。
【讨论】:
这和使用Wait-job不一样吗? 我想说的是,我不认为 OP 想要那样。他们想要的是当父母关闭(并且应该关闭)时作业仍然运行,但不应该等待作业。但我可能错了:) 不知道,其实我不介意,我只是给个办法,而且Wait-job比较短,可以帮到别人。以上是关于如何在 Powershell 中开始一个比它的父级寿命更长的后台作业?的主要内容,如果未能解决你的问题,请参考以下文章