Как я могу запустить фоновую работу в Powershell, которая переживает своего родителя? - PullRequest
16 голосов
/ 15 декабря 2011

Рассмотрим следующий код:

start-job -scriptblock { sleep 10; cmd /c set > c:\env.txt; }
exit

Фоновое задание завершается при выходе из родительского процесса, поэтому вызов cmd.exe никогда не происходит. Я хотел бы написать некоторый подобный код, такой, чтобы родительский элемент немедленно завершился, а дочерний элемент продолжал работать в фоновом режиме.

Я бы хотел сохранить все в одном сценарии, если это возможно.

Ответы [ 4 ]

14 голосов
/ 15 декабря 2011

Вам нужно будет начать процесс:

start-process powershell -ArgumentList "sleep 10; cmd /c set > c:\env.txt" -WindowStyle hidden
4 голосов
/ 08 декабря 2017

Если вы используете 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.

1 голос
/ 30 августа 2016

Если обнаружено, что с помощью 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 подходит для запуска программ на другом компьютере, поэтому родитель никогда не может иметь для него значения)

1 голос
/ 15 декабря 2011

Вы также можете сделать это так

$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

Ваш сценарий будет ожидать окончания конца блока сценария.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...