Событие InvocationStateChanged дважды возникает в сценарии PowerShell

Я пишу сценарий в PowerShell V4 для Windows 8.1, который использует фоновые процессы и события. Я нашел кое-что немного странное. Вместо того, чтобы публиковать около 2500 строк моего сценария, я включил гораздо более короткую программу, которая демонстрирует странное поведение. Я ожидаю, что это что-то, что я делаю неправильно, но я не вижу, в чем проблема. Код выглядит следующим образом:

`

# Scriptblocks to simulate the background task and the action to
# take when an event is raised

[scriptblock] $MyScript = {
    for ($i = 0;$i -lt 30;$i++)
    {
        [console]::writeline("This is a test - $i")
        start-sleep -m 500
    }
}

[scriptblock] $StateChanged = {
    [console]::writeline("The state changed")
}

#  Create a runspace pool

$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, [int] $env:NUMBER_OF_PROCESSORS + 1)
$RunspacePool.ApartmentState = "MTA"
$RunspacePool.Open()

#  Create and start the background task to run

$PS = [powershell]::Create()
[void] $PS.AddScript($MyScript)
$PS.RunspacePool = $RunspacePool
$Asyncresult = $PS.BeginInvoke()

#  Register an interest in the InvocationStateChanged event for
#  the background task. Should the event happen (which it will)
#  run the $StateChanged scriptblock

Register-ObjectEvent -InputObject $PS -EventName InvocationStateChanged -Action $StateChanged

#  The loop that simulates the main purpose of the script

[int] $j = 0
while ($PS.InvocationStateInfo.State -eq [System.Management.Automation.PSInvocationState]::Running)
{
    if ($j -eq 2)
    {
        [void] $PS.BeginStop($NULL, $NULL)
    }
    "Running: $j" | out-host
    sleep -m 400
    $j = $j + 1
}

sleep 10

`

По сути, все, что он делает, это создает пространство выполнения для запуска блока сценария powershell, и пока он работает, что-то еще происходит на переднем плане. Я моделирую, как кто-то нажимает кнопку или, по какой-либо причине, выполняется метод begintop для остановки фонового процесса. Это все работает, и фоновый процесс должным образом останавливается. Однако я зарегистрировал событие для фонового сценария PowerShell, который запускает блок сценария, когда фоновое задание меняет состояние. Странно то, что блок сценария вызывается дважды, и я не могу понять, почему.

Вот некоторый результат запуска скрипта:

E:\Test Programs>powershell -file .\strange.ps1 This is a test - 0 Running: 0 This is a test - 1 Running: 1 The state changed Running: 2 The state changed E:\Test Programs>

Как видите, он дважды отображает «Состояние изменено». Их разделяет доля секунды. Я поставил sleep 10 в конце, чтобы исключить возможность того, что именно остановка скрипта вызывает второе сообщение «Состояние изменилось».

Если кто-нибудь может объяснить, что не так, я был бы очень благодарен.


person Colin    schedule 30.03.2018    source источник
comment
У меня есть немного больше информации, и я надеюсь, что добавление ее в качестве комментария - правильный способ сделать это. Я попытался запустить его в ISE и установить точку останова на единственной строке в блоке сценария StateChanged. Когда я запускаю его, он останавливается на этой строке, как и ожидалось. один шаг, он переходит к закрывающей фигурной скобке затем, а затем на следующем шаге возвращается к первой строке в блоке сценария. Еще один шаг идет к фигурной скобке и еще один выходит из блока сценария. Я не знаю, почему он это делает, но оператор break в конце останавливает его.   -  person Colin    schedule 01.04.2018


Ответы (2)


Событие InvocationStateChanged, вероятно, вызывается, когда Running и Completed

Если вы измените $StateChanged, чтобы также включить свойства автоматической переменной $Sender.InvocationStateInfo.State, например:

[scriptblock] $StateChanged = {
    [console]::writeline("The state changed to: $($Sender.InvocationStateInfo.State)")
}

Ваш вывод, вероятно, будет выглядеть так:

This is a test - 0
Running: 0
This is a test - 1
Running: 1
The state changed to: Running
Running: 2
The state changed: Completed
person jreed121    schedule 10.12.2019

Мне очень жаль, что я не ответил полтора года назад, как я должен был сделать. У меня почему-то никогда не было уведомления о том, что есть ответ и, честно говоря, я просто забыл проверить.

В любом случае, спасибо за ответ. У меня все еще есть мой небольшой тестовый сценарий, хотя то, что я на самом деле писал, было удалено и переписано, но я проверил свой небольшой тестовый сценарий и получил следующее:

Running: 0
Running: 1
This is a test - 1
The state changed to: Stopped
The state changed to: Stopped
Running: 2

Теперь это на Windows 10.

О, в любом случае спасибо за предложение. Как я уже сказал, я переписал исходный сценарий, так что теперь это просто для интереса.

С наилучшими пожеланиями........ Колин

person Colin    schedule 14.04.2021