Powershell 为什么不';添加事件名与计时器一起工作?

Powershell 为什么不';添加事件名与计时器一起工作?,powershell,powershell-2.0,powershell-3.0,Powershell,Powershell 2.0,Powershell 3.0,在PowerShell中,您可以使用对象的add_nameofent({scriptblock})-方法订阅事件。这对按钮等表单对象很有效。但是,当我用System.Timers.Timer尝试它时,它不起作用。为什么呢?样本: $timer1 = New-Object System.Timers.Timer $timer1.Interval = 2000 $timer1.add_Elapsed({ Write-Host "Timer1 tick" }) $timer2 = New-Objec

在PowerShell中,您可以使用对象的
add_nameofent({scriptblock})
-方法订阅事件。这对按钮等表单对象很有效。但是,当我用
System.Timers.Timer
尝试它时,它不起作用。为什么呢?样本:

$timer1 = New-Object System.Timers.Timer
$timer1.Interval = 2000
$timer1.add_Elapsed({ Write-Host "Timer1 tick" })

$timer2 = New-Object System.Timers.Timer
$timer2.Interval = 2000
Register-ObjectEvent -InputObject $timer2 -EventName Elapsed -Action { Write-Host "Timer2 tick" }

$timer1.Start()
$timer2.Start()
$timer2
可以正常工作,但
$timer1
永远不会写入控制台。是什么使计时器与表单组件(其中的添加方法有效)不同?
计时器是否在单独的线程中运行,并因此写入“隐藏”控制台

证明该方法适用于不熟悉该方法的人员的表单组件:

PS > Add-Type -AssemblyName System.Windows.Forms
PS > $b = New-Object System.Windows.Forms.Button
PS > $b.add_click({ Write-Host "button" })
#Get-EventSubscriber won't show this event, but it's added
PS > $b.PerformClick()
button
向我指示您必须订阅事件才能在PowerShell引擎中引发它们。您似乎已经了解了
$timer2的概念。
我一直在自己的会话中尝试启动
$timer1
,但使用公开的方法似乎不起作用,如果您尝试以下代码,我特别指的是
.start()

$w = new-object 'System.Windows.Forms.Form'
$timer1 = New-Object System.Timers.Timer
$timer1.Interval = 2000
$timer1.add_Elapsed({ Write-Host "Timer1 tick" })
$timer1.SynchronizingObject = $w
$timer1.Start()
$w.ShowDialog()
您将看到预期的行为,因为System.Timers.Timer可以与窗口窗体同步(如在c#代码中)

powershell控制台中的问题是,计时器是在不同的线程中创建的,无法与控制台同步,因为它没有公开表示用于封送间隔已过时发出的事件处理程序调用的对象的
ISynchronizeInvoke
接口

SynchronizingObject
null
时,将对系统线程池中的线程调用处理已用事件的方法

IMO幕后注册ObjectEvent创建系统线程池以完成事件处理程序调用


我无法手动重新创建
Register ObjectEvent
的功能,但我认为使用一些c#/Pinvoke代码是可能的。

我知道您需要订阅该事件,但这正是
add_eventname
的快捷方式。若要让脚本块直接处理.NET事件,请调用该对象的Add_event()方法“source:”。如上所述,此快捷方式适用于.net表单组件,那么是什么使它们与.net计时器不同呢此方法也可能特定于表单,我不确定为什么它会在powershell中使用Get-Member-Force cmdlet公开。然而,由于没有在get成员上使用force参数,add_event()就不会在powershell中公开,我觉得这可能是故意的。我还注意到,在您链接的源代码中,他提到使用Add_Event(),但从未实际使用过它。相反,作者注册事件。此文档表明Timer类没有add_event()方法。它接受eventhandler的值。我不打算在这里写一本书来解释它是如何工作的。重要的是,问题不在于方法。这是另外一回事。例如,计时器在一个单独的会话/线程/任何东西中运行,因此它没有连接到我的powershell控制台,因此无法写入它。我想我需要超级英雄的帮助。我需要Keith Hill和Shay Levi!:PI不得不怀疑,这种特殊的方法是否仅仅是凡人无法使用的“仅供内部使用”。我不知道你为什么要这么做。似乎如果你真的可以启用它,那么每次ET在计时器上改变时,你都会生成一个事件,你唯一能完成的事情就是吃掉一个核心,以比你可能处理它们更快的速度生成事件。我不明白。
add_appeased
中的操作仅在计时器已过(勾选)时触发,就像使用
register objectevent
时一样。然而,它写起来更短(更难搞错打字错误)。至于“仅限内部使用”,则不应如此,因为他们在Technet文档中使用了:+1,这是一个很好的答案。在我询问之前,我已经阅读了synchronizingobject,我想您可以用来在表单中添加控件的普通添加控件方法也会设置synchronizingobject属性。但是,必须有一个变量/对象可以用来将计时器与控制台同步。我认为这是正确的答案,但会等待几天来标记它,以防有人能提供完整的解决方案(不创建哑形式):- GrimeWe。我希望@ X0N能给出更好的,他对PortSebe Evin有很深的了解。不管怎样,我发现你的问题真的很有趣!