Следующий блок кода сгенерирует 100 подписок на события WMI.Этот конкретный случай является лишь примером и будет записывать строку в файл (100 раз) всякий раз, когда подключена клавиатура:
$KeyboardQuery = "SELECT * FROM __InstanceCreationEvent Within 1 WHERE TargetInstance ISA 'Win32_Keyboard'"
for ($i = 0; $i -lt 100; $i++) {
Register-WmiEvent -Query $KeyboardQuery -Action {
"A keyboard was just inserted." >> ~\event-log.txt
}
}
Когда это выполняется в PowerShell, процесс WmiPrvSE.exe
потребляет 30% -40% ЦП.Если затем выполняется следующее, подписки на события удаляются и WmiPrvSE.exe
падает до нормального уровня использования ЦП или закрывается вообще:
Get-EventSubscriber | Unregister-Event
Все это работает, как ожидалось.Однако, если окно PowerShell закрывается до запуска Get-EventSubscriber | Unregister-Event
, WmiPrvSE.exe
не завершается и продолжает использовать 30% -40% ЦП.Когда клавиатура вставлена, строка больше не записывается в файл.Если открывается новое окно PowerShell, Get-EventSubscriber
или Get-EventSubscriber -Force
не может найти подписчиков события.Если все экземпляры WmiPrvSE.exe
принудительно закрыты, они запускаются снова и продолжают потреблять 30% -40% ЦП. Даже после выхода из системы и повторного входа WmiPrvSE.exe
продолжает потреблять ЦП. Единственный найденный мной способ завершить эти подписки на события - это перезагрузить компьютер.
Как завершить работуподписки на события, которые были начаты в предыдущем сеансе PowerShell?
Обновление
Я обнаружил, что использование ЦП потерянными подписками на события можно прекратить, вызвав событие, на которое они подписаны.даже если кажется, что они не запускают код в блоке действий после закрытия окна PowerShell.Таким образом, в этом случае при подключении клавиатуры после закрытия PowerShell WmiPrvSE.exe
возвращается к своему нормальному поведению.Это похоже на то, что подписки на события ожидают запуска события в последний раз, прежде чем их можно будет очистить, но теперь они принадлежат самой системе WMI.