Как упоминается в комментариях Lieven Keersmaekers, блок finally не получает шансов на запуск, когда вы используете End для прерывания задачи. Это потому, что Конец просто убивает процесс. PowerShell с удовольствием запустил бы блок finally, прежде чем делать другие важные действия, но PowerShell вообще ничего не может сделать после сигнала завершения процесса - он мертв. Ни один процесс не может справиться с этим. По словам Раймонда Чена :
TerminateProcess - это низкоуровневая функция уничтожения процессов. Он обходит DLL_PROCESS_DETACH и все остальное в процессе. Как только вы завершите работу с TerminateProcess, в этом процессе больше не будет кода пользовательского режима. Это ушло Не проходи иди. Не собирайте 200 долларов.
Однако есть обходной путь. Поскольку команда End в планировщике заданий не уничтожает подпроцессы процесса задания, ваш основной сценарий PowerShell может запустить сторожевой процесс для выполнения окончательной очистки. Этот скрипт может выглядеть примерно так (назовем его watchdog.ps1
):
$watched = Get-Process -Id $args[0] $watched.WaitForExit() 'Cleanup' >> c:\test.log
Он принимает идентификатор процесса, ожидает, пока этот процесс завершится, и только после этого выполняет некоторую очистку, эквивалентную вашему блоку finally.
Тогда ваш основной скрипт может выглядеть так:
$myPid = [System.Diagnostics.Process]::GetCurrentProcess().Id $watchdog = Start-Process 'powershell' "-c .\watchdog.ps1 $myPid" -PassThru -WindowStyle Hidden 'Starting' sleep 10 'Finished'
В начале он запускает сторожевой скрипт, предоставляя свой собственный идентификатор процесса. Затем он идет своим обычным делом, выходя нормально, как только это будет сделано.
Если вы хотите, чтобы очистка сторожевого таймера происходила только в случае прерывания основного сценария, добавьте эту строку в конец основного сценария:
$watchdog.Kill()
Это предотвратит выход сторожа за пределы второй линии.
Ваше перенаправление будет применяться только к основному процессу, поэтому сторожевой таймер должен обрабатывать собственное направление вывода. В зависимости от конфигурации вашей запланированной задачи вам может понадобиться указать полный путь к сценарию watchdog в команде watchdog-launching основного сценария.