<< Back to Script Library
Force Power Off Generic VM
This script uses the CUActions available in v8.8 onwards to force power off VMs on any supported hypervisor. It can be used as a right-click action or as an automated action by a trigger.
The Script
Copy Script
Copied to clipboard
<#
.SYNOPSIS
This script performs a Force Power Off on a VM
.DESCRIPTION
This script performs a Force Power Off on a VM. The script uses the CU Actions in version 8.8 to action the power-off, regardless of the underlying hypervisor.
.PARAMETER hostname
The hostname to perform the action on, supplied via a trigger or right-click action against a VM
.NOTES
Version: 0.1
Context: Computer, executes on Monitor
Author: Bill Powell
Requires: Realtime DX 8.8
Creation Date: 2023-05-11
.LINK
https://support.controlup.com/docs/powershell-cmdlets-for-solve-actions
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, HelpMessage = 'hostname of machine to be actioned')]
[ValidateNotNullOrEmpty()]
[string]$hostname
)
#region ControlUpScriptingStandards
$VerbosePreference = $(if( $PSBoundParameters[ 'verbose' ] ) { $VerbosePreference } else { 'SilentlyContinue' })
$DebugPreference = $(if( $PSBoundParameters[ 'debug' ] ) { $DebugPreference } else { 'SilentlyContinue' })
$ErrorActionPreference = $(if( $PSBoundParameters[ 'erroraction' ] ) { $ErrorActionPreference } else { 'Stop' })
$ProgressPreference = 'SilentlyContinue'
[int]$outputWidth = 400
if( ( $PSWindow = (Get-Host).UI.RawUI ) -and ( $WideDimensions = $PSWindow.BufferSize ) )
{
$WideDimensions.Width = $outputWidth
$PSWindow.BufferSize = $WideDimensions
}
#endregion ControlUpScriptingStandards
#region Define the CUAction
$RequiredAction = "Force Power Off VM" # or any of "Force Power Off VM","Force Reset VM","Power On VM","Restart Guest","Shutdown Guest"
$RequiredActionCategory = 'VM Power Management'
#endregion
#region Process Args
#$hostname = $args[0] # the computername is passed as the only argument
#endregion
#region Load the version of the module to match the running monitor and check that it has the new features
function Get-MonitorDLLs {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)][string[]]$DLLList
)
[int]$DLLsFound = 0
Get-CimInstance -Query "SELECT * from win32_Service WHERE Name = 'cuMonitor' AND State = 'Running'" | ForEach-Object {
$MonitorService = $_
if ($MonitorService.PathName -match '^(?<op>"{0,1})\b(?<text>[^"]*)\1$') {
$Path = $Matches.text
$MonitorFolder = Split-Path -Path $Path -Parent
$DLLList | ForEach-Object {
$DLLBase = $_
$DllPath = Join-Path -Path $MonitorFolder -ChildPath $DLLBase
if (Test-Path -LiteralPath $DllPath) {
$DllPath
$DLLsFound++
}
else {
throw "DLL $DllPath not found in running monitor folder"
}
}
}
}
if ($DLLsFound -ne $DLLList.Count) {
throw "cuMonitor is not installed or not running"
}
}
$AcceptableModules = New-Object System.Collections.Generic.List[object]
try {
$DllsToLoad = Get-MonitorDLLs -DLLList @('ControlUp.PowerShell.User.dll')
$DllsToLoad | Import-Module
$DllsToLoad -replace "^.*\\",'' -replace "\.dll$",'' | ForEach-Object {$AcceptableModules.Add($_)}
}
catch {
$exception = $_
Write-Error "Required DLLs not loaded: $($exception.Exception.Message)"
}
if (-not ((Get-Command -Name 'Invoke-CUAction' -ErrorAction SilentlyContinue).Source) -in $AcceptableModules) {
Write-Error "ControlUp version 8.8 commands are not available on this system"
exit 0
}
#endregion
#region Perform CUAction on target
$ThisComputer = Get-CimInstance -ClassName Win32_ComputerSystem
Write-Output "Action $RequiredAction applied to $hostname from $($ThisComputer.Name)"
$Action = (Get-CUAvailableActions -DisplayName $RequiredAction | Where-Object {($_.Title -eq $RequiredAction) -and ($_.IsSBA -eq $false) -and ($_.Category -eq $RequiredActionCategory)})[0]
$Allrows = Invoke-CUQuery -Table $Action.Table -Fields * -Where "sName = '${hostname}'"
$Allrows.Data | ForEach-Object {
$VMTableRow = $_
$Result = Invoke-CUAction -ActionId $Action.Id `
-Table $Action.Table `
-RecordsGuids @($VMTableRow.key)
Write-Output "Action $RequiredAction applied to $hostname, result $($Result.Result)"
}
#endregion
Write-Output "Done"