Skip to content

Instantly share code, notes, and snippets.

@CrookedJ
Created December 14, 2025 16:13
Show Gist options
  • Select an option

  • Save CrookedJ/ad22d4db861c5f5b3b04f3383c01a194 to your computer and use it in GitHub Desktop.

Select an option

Save CrookedJ/ad22d4db861c5f5b3b04f3383c01a194 to your computer and use it in GitHub Desktop.
function Get-TaskPlus {
[CmdletBinding(SupportsShouldProcess)]
param(
[VMware.VimAutomation.ViCore.Impl.V1.Alarm.AlarmDefinitionImpl]$Alarm,
[Parameter(ValueFromPipeline)]
[VMware.VimAutomation.ViCore.Impl.V1.Inventory.InventoryItemImpl]$Entity,
[switch]$Recurse = $false,
[VMware.Vim.TaskInfoState[]]$State,
[DateTime]$Start,
[DateTime]$End,
[string]$UserName,
[int]$MaxSamples = 100,
[VMware.VimAutomation.ViCore.Impl.V1.VIServerImpl[]]$Server = $global:DefaultVIServer,
[int]$WindowSize = 100
)
process {
Write-Verbose $Entity
$filter = New-Object VMware.Vim.TaskFilterSpec
if ($Alarm) {
$filter.Alarm = $Alarm.ExtensionData.MoRef
}
if ($Entity) {
$filter.Entity = New-Object VMware.Vim.TaskFilterSpecByEntity
$filter.Entity.entity = $Entity.ExtensionData.MoRef
if ($Recurse) {
$filter.Entity.Recursion = [VMware.Vim.TaskFilterSpecRecursionOption]::all
}
else {
$filter.Entity.Recursion = [VMware.Vim.TaskFilterSpecRecursionOption]::self
}
}
if ($State) {
$filter.State = $State
}
if ($Start -or $Finish) {
$filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime
$filter.Time.beginTime = $Start
$filter.Time.endTime = $End
$filter.Time.timeType = [vmware.vim.taskfilterspectimeoption]::startedTime
}
if ($UserName) {
$userNameFilterSpec = New-Object VMware.Vim.TaskFilterSpecByUserName
$userNameFilterSpec.UserList = $UserName
$filter.UserName = $userNameFilterSpec
}
$nrTasks = 0
foreach ($viObject in $Server) {
$si = Get-View ServiceInstance -Server $viObject
$tskMgr = Get-View $si.Content.TaskManager -Server $viObject
if ($tskMgr.recentTask) {
$tasks = Get-View $tskMgr.recentTask -Server $viObject
$selectNr = [Math]::Min($tasks.Count, $MaxSamples - $nrTasks)
Get-TaskDetails -Tasks $tasks[0..($selectNr - 1)] -VIServer $viObject.Name
$nrTasks += $selectNr
}
$tCollector = Get-View ($tskMgr.CreateCollectorForTasks($filter)) -Server $viObject
$taskReadOp = $tCollector.ReadNextTasks
do {
$tasks = $taskReadOp.Invoke($WindowSize)
if (!$tasks) { break }
$selectNr = [Math]::Min($tasks.Count, $MaxSamples - $nrTasks)
Get-TaskDetails -Tasks $tasks[0..($selectNr - 1)] -VIServer $viObject.Name
$nrTasks += $selectNr
} while ($nrTasks -lt $MaxSamples)
$tCollector.DestroyCollector()
}
}
}
function Get-TaskDetails {
[CmdletBinding()]
param(
[VMware.Vim.TaskInfo[]]$Tasks,
[string]$VIServer
)
process {
$tasks | ForEach-Object {
$object = [ordered]@{ }
$object.Add('Name', $_.Name)
$object.Add('Description', $_.Description.Message)
$object.Add('DescriptionId', $_.DescriptionId)
$object.Add('CreateTime', $_.QueueTime)
$object.Add('StartTime', $_.StartTime)
$object.Add('EndTime', $_.CompleteTime)
$object.Add('ExecutionTime', $($duration = $_.CompleteTime - $_.StartTime; '{0}h {1}m {2}.{3}s' -f $duration.Hours, $duration.Minutes, $duration.Seconds, $duration.Milliseconds.ToString().PadLeft(3,'0')))
$object.Add('State', $_.State)
$object.Add('Result', $_.Result)
$object.Add('Entity', $_.EntityName)
$object.Add('VIServer', $Server)
$object.Add('Error', $_.Error.LocalizedMessage)
$object.Add('Cancelled', $_.Cancelled)
$object.Add('Reason', $(try {$_.Reason.GetType().Name -replace 'TaskReason'} catch { $_.Reason }))
$object.Add('AlarmName', $_.Reason.AlarmName)
$object.Add('AlarmEntity', $_.Reason.EntityName)
$object.Add('ScheduleName', $_.Reason.Name)
$object.Add('User', $_.Reason.UserName)
$object.Add('Key', $_.Key)
$object.Add('ParentKey', $_.ParentTaskKey)
$object.Add('RootKey', $_.RootTaskKey)
New-Object PSObject -Property $object
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment