Programmatically Detecting when a VM Changes State
Every now and then I get asked how to detect whenever a virtual machine changes state. Usually, people who ask about this have written some code that periodically queries Hyper-V to see what state different virtual machines are in (stopped, running, etc.). What they find is that this is not efficient – and it sometimes misses a virtual machine that has quickly changed state (e.g. stopped and started again).
Luckily, there is a way to be notified of virtual machine state changes without polling for information.
To do this – you want to use WMI instance modification events:
# WMI Query that specifies what events we will watch for
$Query = "Select * from __InstanceModificationEvent within 3 where TargetInstance ISA 'MSVM_ComputerSystem' `
and TargetInstance.EnabledState <> PreviousInstance.EnabledState"
# Script block that will run whenever the event fires
[ScriptBlock]$Action = {
$VMName = $Event.SourceEventArgs.NewEvent.TargetInstance.ElementName
switch ($Event.SourceEventArgs.NewEvent.TargetInstance.EnabledState)
{
2 {$vmState = "running"}
3 {$vmState = "turned off"}
9 {$vmState = "paused"}
6 {$vmState = "in a saved state"}
10 {$vmState = "starting"}
4 {$vmState = "stopping"}
default {$vmState = "in an unknown state..."}
}
if ($Event.SourceEventArgs.NewEvent.TargetInstance.EnabledState -eq 1)
{$vmState = $Event.SourceEventArgs.NewEvent.TargetInstance.OtherEnabledState}
write-host "The virtual machine '$($vmName)' is now $($vmState)."}
# Register for the events
Register-WMIEvent -Query $Query -Action $Action -Namespace root\virtualization\v2
# To clean up - run "Get-EventSubscriber | Unregister-Event"
This code will print out a message whenever a virtual machine changes state.
Cheers,
Ben
Comments
Anonymous
June 13, 2014
An event listener is what that is. Ben, what about HA virtual machines? Don't we have to register a listener with Failover Clustering?Anonymous
February 09, 2015
Not a powershell guru, and am truly looking for something that can run/be configured to shoot out an email whenever the state of ANY VM on the Hyper-V host changes. What would an example of running this script in powershell look like? Thanks, Tim