Registering for WMI Events in PowerShell
An alternate title might be ‘Running PowerShell Code ONLY when the power state changes’, because that was the very interesting task I received from my customer this week.
It was honestly too cool of a StackOverflow answer NOT to share, so here it goes, you can vote for it here if you thought it was worth-while.
If you want your code to trigger only when the System Power State changes, as described here, use this code.
Register-WMIEvent -query "Select \* From Win32\_PowerManagementEvent" \` -sourceIdentifier "Power" \` -action { #YourCodeHere }
Now, this will trigger whenever the power state changes, whether you plug the device in, OR unplug it. So you might further want to stop and pause to ask the question:
Am I on power or not?
Fortunately we can use the WMI Class Win32_BatteryStatus to detect if we’re charging or not, so here’s the full construct that I use to ONLY run an operation when a power event changes, and then only if I’m no longer on Power.
Locking the workstation when the system is unplugged
Register-WMIEvent -query "Select * From Win32_PowerManagementEvent" `
-sourceIdentifier "Power" `
-action {
if ([BOOL](Get-WmiObject -Class BatteryStatus -Namespace root\wmi).PowerOnLine ){
#Device is plugged in now, do this action
write-host "Power on!"
}
else{
#Device is NOT plugged in now, do this action
write-host "Now on battery, locking..."
[NativeMethods]::LockWorkStation()
}
If you’re curious how this looks in real time
Using PowerShell to register for a WMI event, to lock a workstation on power state change pic.twitter.com/JtJWDosA4b
— Stephen Owen 🦊Deploy (@FoxDeploy) December 15, 2016
Registering for device events
It can also be useful to have your code wait for something to happen with devices, such as running an action when a device is added or removed. To do this, use this code.
#Register for power state change
#Where TargetInstance ISA 'Win32_Process'"
Register-WMIEvent -query "Select * From Win32_DeviceChangeEvent where EventType = '2'" `
-sourceIdentifier "Power" `
-action {#Do Something when a device is added
Write-host "Device added at $(Get-date)"
}
You might also want to do an action if a device is removed instead, so use this table to choose which event is right for you. Read more about it here.
EventType | Id |
---|---|
ConfigurationChanged | 1 |
Device Arrived | 2 |
Device Removed | 3 |
Device Docked | 4 |
What else can I wait for?
Not only these, but you can trigger your code to execute on a variety of useful WMI Events, all of which can be seen in this image below!
ClassName | Triggers when |
Win32_DeviceChangeEvent | A device is installed, removed, or deleted, or the system is docked |
Win32_VolumeChangeEvent | Something happens to your disk drives |
Win32_PowerManagementEvent | Your device is plugged, unplugged or docked |
Win32_ComputerSystemEvent | Something major happens to the system |
Win32_ComputerShutdownEvent | The system is shutting down! |
RegistryEvent | Anythign happens to the registry |
RegistryKeyChangeEvent | A reg key you specify is changed |
RegistryValueChangeEvent | A reg value you specify is changed |