Vbscript 取消使用ExecutionQuery创建的WMI事件通知

Vbscript 取消使用ExecutionQuery创建的WMI事件通知,vbscript,wmi,Vbscript,Wmi,我可以在脚本中创建非永久性WMI事件查询,例如此脚本,它记录接下来5个新Notepad.exe进程的PID: Set WMI=GetObject(“winmgmts:\\。\ROOT\cimv2”) wql=“从2”内的InstanceCreationEvent选择* “其中TargetInstance ISA'Win32_Process'和TargetInstance.Name='Notepad.exe'” Set-EventSource=WMI.ExecutionQuery(wql) 对于i

我可以在脚本中创建非永久性WMI事件查询,例如此脚本,它记录接下来5个新Notepad.exe进程的PID:

Set WMI=GetObject(“winmgmts:\\。\ROOT\cimv2”)
wql=“从2”内的InstanceCreationEvent选择*
“其中TargetInstance ISA'Win32_Process'和TargetInstance.Name='Notepad.exe'”
Set-EventSource=WMI.ExecutionQuery(wql)
对于i=1到5
使用EventSource.NextEvent(-1)
Wscript.Echo.TargetInstance.ProcessId
以
下一个
但是我缺少一种明确取消
EventSource
的方法。否则,事件通知将在WMI内无限期运行,即使侦听生成事件的脚本因任何原因终止(*)。当脚本多次运行时,这将导致增加开销

MSDN说:

方法执行一个查询以接收事件。调用立即返回,用户可以在事件到达时轮询返回的枚举数。释放返回的枚举数将取消查询

如何释放返回的枚举数

EventSource
对象似乎不可枚举。尝试对其上的每个使用
“VBScript运行时错误:对象不支持此属性或方法”失败,因此我无法在每个
循环的
末尾使用隐式的
释放


(*)这源于说明“释放返回的枚举数会取消查询”的文档,这意味着不释放枚举数会导致查询持续存在,但也可以明确确认:

设置此查询的通知
“从2内的uu InstanceCreationEvent中选择*,其中TargetInstance是'Win32\u Directory'和TargetInstance.Name='C:\\Test'
,并用于观察来自WMI服务的文件系统访问(
WmiPrvSE.exe
)。WMI服务将每隔2秒开始轮询名为“C:\Test”的文件夹,并在设置监视的脚本结束后继续轮询

重新启动WMI服务可以消除轮询,但显然对于这种情况,这不是一个好的解决方案。

您可以改用它吗?通过这种方式,您可以传递一个消息,稍后可以调用该消息来取消接收器,该消息还应删除与该接收器关联的任何事件使用者

使用
ExecNotificationQuery()
方法的问题在于,它只允许您访问
SWbemEventSource
对象,该对象允许调用枚举器中的下一个事件。在注册事件使用者之后,似乎不可能使用该方法删除它

运行此:

Set FSO=CreateObject(“Scripting.FileSystemObject”)
设置WMI=GetObject(“winmgmts:\\.\ROOT\cimv2”)
设置Sink=WScript.CreateObject(“WbemScripting.SWbemSink”、“Sink_389;”)
wql=“从2”内的InstanceCreationEvent中选择*_
“其中TargetInstance ISA'Win32_Directory'和TargetInstance.Name='C:\\Test'”
Echo“正在等待事件…”
WMI.ExecuteNotificationQueryAsync接收器,wql
对于i=1到10
Echo i
Wscript.Sleep 1000
如果i=5,那么
FSO.CreateFolder“C:\Test”
Echo“已创建测试文件夹”
如果结束
下一个
下沉,取消
Echo“接收器已取消”
FSO.delete文件夹“C:\Test”
Echo“已删除测试文件夹。”
子接收器\u OnObjectReady(eventObject,asyncContext)
设置文件夹=eventObject.TargetInstance
WScript.Echo“\uuu InstanceCreationEvent:”&folder.Name
端接头
输出与此类似的内容:

Waiting for events... 1 2 3 4 5 Test folder created. 6 7 __InstanceCreationEvent: C:\Test 8 9 10 Sink canceled. Test folder deleted. 等待事件。。。 1. 2. 3. 4. 5. 已创建测试文件夹。 6. 7. __InstanceCreationEvent:C:\Test 8. 9 10 水槽取消了。 测试文件夹已删除。 之后,Process Monitor将确认WMI已停止后台轮询以创建文件夹


警告:调用
Sink.Cancel
是绝对必要的。如果脚本意外终止,WMI将继续在后台轮询,重新启动WMI服务是摆脱轮询循环的唯一方法。

关于
Set EventSource=Nothing
?@user692942否,这没有帮助。脚本退出时仍会发生这种情况。但是WMI事件查询是这样的:您向WMI服务发送一个查询。WMI服务在内部设置对请求条件的监视,并返回侦听生成事件的方法。在VBScript中将事件侦听器设置为
Nothing
,不会破坏机制的WMI内部部分。是的,但这不是您正在设置的永久事件使用者,而是临时事件使用者,它们的工作方式不同。这就是为什么要停止脚本退出通常带有脚本延迟。您是否已经确定事件侦听器是在脚本完成后被保留的,还是仅仅是一种假设?查看您最近的编辑,它听起来像是在保留事件,因此您可能希望调用并传入。我不是WMI方面的专家,我只是提供一些建议。@user692942不,你的想法是对的。取消异步接收器实际上可以做到这一点。不错。:)你能把它变成一个答案吗?很高兴这个例子成功了,非常好的例子,谢谢你把它添加到答案中。太糟糕了,似乎没有弹性的方法用VBScript来做这件事。我想知道PowerShell是否能做得更好。