在PowerShell脚本中引发两次InvocationStateChanged事件

问题描述 投票:1回答:1

我一直在Windows 8.1的PowerShell V4中编写脚本,该脚本利用了后台进程和事件。我发现了一些奇怪的东西。与其发布我的脚本中的大约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脚本块,而在运行时,其他操作会在前台发生。我模拟有人按下某个按钮,或者出于某种原因而执行了beginstop方法以停止后台进程。一切正常,后台进程适当停止。但是,我已经为后台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,以消除脚本停止导致第二条“状态已更改”消息的可能性。

如果有人能解释什么地方出了问题,我将非常感激。

powershell events runspace
1个回答
0
投票

InvocationStateChangedRunning上的事件很可能被调用

如果将Completed更改为还包括$StateChanged自动变量属性,如下所示:

$Sender.InvocationStateInfo.State

您的输出可能看起来像:

[scriptblock] $StateChanged = {
    [console]::writeline("The state changed to: $($Sender.InvocationStateInfo.State)")
}
© www.soinside.com 2019 - 2024. All rights reserved.