如何让 WMI 订阅者从脚本运行?

如何让 WMI 订阅者从脚本运行?

我正在尝试从 Powershell 脚本文件内部注册 WMI 事件处理程序。

这是我正在测试的完整脚本。

$RegPath = 'HKCU:\Test\'
$Query = "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PnPEntity'"
Register-WmiEvent -Query $Query -SourceIdentifier "Handler" -Action { Set-ItemProperty -Path $RegPath -Name 'test' -Value '1'}

在运行脚本之前,确实需要设置一个新的注册表项。此时HKCUTest需要创建该项。事件处理程序将test属性添加到此项并为其赋值。为了测试脚本,我删除了该test属性并将任何 USB 设备插入计算机。

当我将这三行粘贴到 Powershell 终端并插入 USB 设备时,它会写入该test属性。如果我将这三个命令保存到文件中ps1,打开 Powershell 终端并从那里运行脚本,它永远不会写入该属性。运行Get-EventSubscriber表明脚本完成后处理程序仍处于注册状态。

我还尝试添加一个循环来强制脚本保持打开状态。粘贴命令并添加 while 循环会将属性写入注册表。脚本永远不会关闭,但也不会将属性写入注册表。

while ($true) {
    start-sleep -seconds 1
}

有什么想法吗?可能是权限问题吗?

PS 版本。

Name                           Value                                                                                                 
----                           -----                                                                                                 
PSVersion                      5.1.19041.3031                                                                                        
PSEdition                      Desktop                                                                                               
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                               
BuildVersion                   10.0.19041.3031                                                                                       
CLRVersion                     4.0.30319.42000                                                                                       
WSManStackVersion              3.0                                                                                                   
PSRemotingProtocolVersion      2.3                                                                                                   
SerializationVersion           1.1.0.1    

答案1

这是一个范围界定问题。当您将其作为脚本运行时,$RegPath仅存在于该脚本的本地范围内,而事件订阅者则在单独的会话中创建。该 Action作业似乎继承了您当前的交互式会话,其中$RegPath未设置。您可以在检查作业输出时看到错误:

Get-Job 'Handler' | select Id,Name,Error

Id Name    Error
-- ----    -----
 1 Handler {Cannot bind argument to parameter 'Path' because it is null.}

简单的解决方法是静态设置路径:

Register-WmiEvent -Action { Set-ItemProperty -Path 'HKCU:\Test\' -Name 'test' -Value '1'} -Query $Query -SourceIdentifier "Handler" 

或者如果它必须是一个变量,请在作业操作脚本块内创建该变量:

Register-WmiEvent -Query $Query -SourceIdentifier "Handler" -Action { 
  $RegPath = 'HKCU:\Test\'
  Set-ItemProperty -Path $RegPath -Name 'test' -Value '1'
}

一些您可以使用从事件本身提取的自动变量:$Event$EventSubscriber$Sender$EventArgs$Args

我还建议你使用注册-CimIndicationEvent而不是Register-WmiEvent。它们完全可以互换,但Register-WMIEvent在较新版本的 powershell 中已被删除。

相关内容