Vbscript 取消使用ExecutionQuery创建的WMI事件通知
我可以在脚本中创建非永久性WMI事件查询,例如此脚本,它记录接下来5个新Notepad.exe进程的PID: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
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是否能做得更好。