在进行代码更改后,PowerShell ISE 有时会出现不可预测的行为 [英] The PowerShell ISE sometimes behaves unpredictably after code changes are made

查看:51
本文介绍了在进行代码更改后,PowerShell ISE 有时会出现不可预测的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using the PowerShell ISE (PS version 5.0). If I run this code:

Write-Host "This"

输出:

This

如果我这样修改脚本:

Write-Host "That"

它输出:

That

太好了.正如预期的那样.现在,如果我有这个代码:

Great. As expected. Now, if I have this code:

$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 而不是那里.如果我关闭 ISE 并重新打开它,脚本会按预期运行.

If I change anything in the script, e.g. "Here" to "There" or $Timer.Interval = 3000 to $Timer.Interval = 4000 and run it, it does two unexpected things: 1.) instead of showing the form for the proper duration of time, it briefly flashes it on the screen, and 2.) it outputs the original Here instead of There. If I close the ISE and re-open it, the script runs as expected.

这是怎么回事?

推荐答案

tl;dr:

  • 定时器实例是在session范围内创建的

  • The timer instance is created in the session scope,

  • 无论您是否在 ISE 中运行脚本,
  • 以及引用它的任何变量是否在范围内.

总是处理定时器(或至少禁用它)以防止它产生更多事件.

Always dispose of a timer (or at least disable it) to prevent it from generating more events.

一般 - 尽管这不是手头问题的原因 - 请注意在 ISE 中隐式地运行脚本dot-sources it,以便重复执行在 相同 范围内运行,并且之前的变量值延迟,这可能导致意外行为.

Generally - although that is not the cause of the problem at hand - be aware that running a script in the ISE implicitly dot-sources it, so that repeated executions run in the same scope, with variable values from previous ones lingering, which can lead to unexpected behavior.

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

Your code never disposes of (or disables) the timer, which therefore:

  • 在整个会话中保持活动状态,无论变量是否引用它

  • stays alive for the entire session, whether or not a variable references it

继续生成事件,

但它们只会在表单显示时触发.

but they only fire while a form is being displayed.

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

This explains your symptom: The queued up, original events fire instantly as soon as you display the form again.

解决方案是处理定时器,一旦它完成任务并触发事件(一次):

The solution is to dispose of the timer once it has done its duty and fired the event (once):

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 的隐式采购行为,重复调用此代码也能按预期工作.

Even with the implicit sourcing behavior of the ISE described above, repeated invocations of this code work as expected.

这篇关于在进行代码更改后,PowerShell ISE 有时会出现不可预测的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆