如何在 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 中开始一个比它的父级寿命更长的后台作业?的主要内容,如果未能解决你的问题,请参考以下文章

QWidget 失去了它的父级

将子视图安装到它的父级?

与 Vue 中的父级同步道具?

mongoose-mpath 模块正在创建文档但未分配给它的父级

jquery如何获得父级的父级元素?

SpringBoot的pom.xml文件的父级.pom文件