我正在尝试从 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'}
在运行脚本之前,确实需要设置一个新的注册表项。此时HKCU
,Test
需要创建该项。事件处理程序将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 中已被删除。