I was working on a script last night to help track power actions in a 10K+ machine environment, and felt compelled to share some scripts I put together to track power actions in a XenDesktop 5.x environment.

The goal of this script is to display a realtime list of active power actions in an effort to validate power state synchronization between the hypervisor and XenDesktop database. I also wanted to track the reason for the power action (admin, idle pool, power policy, etc.), target machine name, and the desktop group that it belongs to. I used the power action’s ActualPriority property to identify the source of the action, and passed the associated machine name to Get-BrokerDesktop to identify the machine’s desktop group.

Here’s the script in it’s current (condensed) form:

# Begin Script

# PowerShell script to monitor power actions in a XenDesktop 5.x site
# Press Ctrl+Q to stop the script cleanly, or Ctrl+C to halt execution

$pollinginterval = 3000 #Polling frequency in ms
asnp citrix.Broker* #Load the Citrix.Broker.Admin PS snap-in
For(;;)
 { $actions = $null; $actions = get-brokerhostingpoweraction -State 'Pending,Started'; $time = Get-Date
 if ($actions) { foreach ($action in $actions) {
 $diff = $time - $action.ActionStartTime; $elapsedsecs = "{0:N0}" -f $diff.TotalSeconds; $desktop = Get-BrokerDesktop -MachineName $action.MachineName
 switch ($action.ActualPriority)
 {
 10 { $actionsource = "'User-driven restart' " }
 20 { $actionsource = "Session Launch " }
 30 { $actionsource = "Admin " }
 33 { $actionsource = "PVD " }
 40 { $actionsource = "'Un-taint' worker " }
 50 { $actionsource = "Power Policy " }
 60 { $actionsource = "Idle Pool " }
 }
 write-output "$($time), UID $($action.UID), $($actionsource)initiated $($action.Action) $($action.State) for $($action.MachineName) in '$($desktop.DesktopGroupName)' $($elapsedsecs) seconds ago" } }
 else { Write-Output "$($time), No running power actions" }
 if ($host.ui.RawUi.KeyAvailable) { $key = $host.ui.RawUI.ReadKey("NoEcho,IncludeKeyUp")
 if (($key.VirtualKeyCode -eq 81) -AND ($key.ControlKeyState -match "LeftCtrlPressed")){ Write-Host "Ctrl+Q Pressed, quitting";break } }
 Start-Sleep -MilliSeconds $PollingInterval }

# End Script

Here’s what the output looks like in a console window:

To run the script, save the above text to a .ps1 file, and execute it in a Powershell console on a member DDC. Be sure to run a ‘Set-Executionpolicy -ExecutionPolicy Unrestricted’ if the default execution policy is blocking unsigned scripts. You can also pipe the output to a text file (.\GetRunningPowerActions.ps1 > log.txt) and use something like BareTail to view the real-time output, while also keeping a running log of actions.

Here’s a similar script to get the same output for completed power actions:

asnp citrix.B*
foreach ($action in get-brokerhostingpoweraction -MaxRecordCount 100 -SortBy -'ActionCompletionTime')
{
 if ($action.State -ne "Pending" -and $action.State -ne "Started")
 {
 $desktop = Get-BrokerDesktop -MachineName $action.MachineName
 switch ($action.ActualPriority)
 {
 10 { $actionsource = "'User-driven restart' " }
 20 { $actionsource = "Session Launch " }
 30 { $actionsource = "Admin " }
 33 { $actionsource = "PVD " }
 40 { $actionsource = "'Un-taint' worker " }
 50 { $actionsource = "Power Policy " }
 60 { $actionsource = "Idle Pool " }
 }
 write-output "UID $($action.UID), $($actionsource)initiated $($action.Action) $($action.State) for $($action.MachineName) in '$($desktop.DesktopGroupName)' at $($action.ActionCompletionTime)"
 }
}