在进行代码更改后,PowerShell ISE有时会出现不可预测的行为

时间:2017-06-01 13:31:16

标签: powershell powershell-ise powershell-v5.0

我使用的是PowerShell ISE(PS 5.0版)。如果我运行此代码:

Write-Host "This"

输出:

This

如果我像这样修改脚本:

Write-Host "That"

输出:

That

大。正如所料。现在,如果我有这个代码:

$Form = New-Object System.Windows.Forms.Form
$Timer = New-Object System.Windows.Forms.Timer

$Timer.Add_Tick(
{
    &{
    Write-Output "Here"
    $Form.Close()} | Write-Host 
})

$Timer.Interval = 3000
$Timer.start()
$result = $Form.ShowDialog()

输出:

Here

如果我在脚本中更改任何,例如"Here""There"$Timer.Interval = 3000$Timer.Interval = 4000并运行它,它会做两件意想不到的事情:1。)而不是在适当的持续时间内显示表单,在屏幕上闪烁,然后2.)它输出原始Here而不是There。如果我关闭ISE并重新打开它,脚本将按预期运行。

发生了什么事?

2 个答案:

答案 0 :(得分:2)

<强> TL;博士

  • 计时器实例是在会话范围中创建的,

    • 是否在ISE中运行脚本,
    • 以及引用它的任何变量是否在范围内。
  • 始终处置计时器(或至少禁用它)以防止它产生更多事件。

  • 一般 - 虽然是手头问题的原因 - 请注意隐式运行ISE 中的脚本dot-sources it ,以便重复执行在相同的范围内运行,其中的变量值来自之前的延迟,这可能会导致意外行为。

您的代码从不处理(或禁用)计时器,因此:

  • 对整个会话保持活跃,无论变量是否引用它

  • 继续生成事件,

  • 但在显示表单时触发

这解释了您的症状:排队,原始事件会在您再次显示表单时立即

解决方案是在完成任务后解除计时器并解除事件(一次):

Add-Type -AssemblyName System.Windows.Forms

$Form = New-Object System.Windows.Forms.Form
$Timer = New-Object System.Windows.Forms.Timer

$Timer.Add_Tick({
    & {
      Write-Output "Here"
      $Form.Close()
    } | Write-Host 
})

$Timer.Interval = 3000
$Timer.Start()
$result = $Form.ShowDialog()
$Timer.Dispose() # IMPORTANT: Dispose of the timer so it won't generate more events.

即使使用上述ISE的隐式源代码行为,此代码的重复调用仍可按预期工作。

答案 1 :(得分:1)

我认为它与ISE中的变量即使在脚本结束后仍然在内存中有关。如果你添加

$Timer.Stop() 

到脚本的最后一行然后关闭并重新打开它将起作用的ISE。