我一直在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
,以消除脚本停止导致第二条“状态已更改”消息的可能性。
如果有人能解释什么地方出了问题,我将非常感激。
InvocationStateChanged
和Running
上的事件很可能被调用
如果将Completed
更改为还包括$StateChanged
自动变量属性,如下所示:
$Sender.InvocationStateInfo.State
您的输出可能看起来像:
[scriptblock] $StateChanged = {
[console]::writeline("The state changed to: $($Sender.InvocationStateInfo.State)")
}