Как упоминается в комментариях 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 основного сценария.