Diagnose Veeam schedules; show "Not scheduled" for no next run
Veeam jobs on a VBR 13 server show no next run on the dashboard. The diagnostics script gains a section dumping each job's schedule properties (ScheduleOptions, GetScheduleOptions(), Get-VBRJobScheduleOptions) and the current culture, to find where VBR 13 keeps the next run. The dashboard showed "Never" for a missing next run, which reads as "this job will never run"; it now says "Not scheduled" (e.g. immediate mode copy jobs). Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
2. sessions whose JobId matches no job (the runs that are going missing)
|
||||
3. for jobs with no matching sessions, their type/link-related properties and methods
|
||||
4. what other job cmdlets (e.g. Get-VBRBackupCopyJob) return
|
||||
5. each job's schedule properties, which the collector reads for the next run
|
||||
Nothing is changed in Veeam or the dashboard. Output is also saved to a text file.
|
||||
|
||||
.EXAMPLE
|
||||
@@ -42,14 +43,14 @@ function Format-Value($Value) {
|
||||
|
||||
# Property and method names matching $LinkPattern, with property values. Every read is guarded:
|
||||
# some Veeam properties throw when accessed.
|
||||
function Show-LinkMembers($Object) {
|
||||
foreach ($p in $Object.PSObject.Properties | Where-Object { $_.Name -match $LinkPattern }) {
|
||||
function Show-LinkMembers($Object, [string]$Pattern = $LinkPattern, [string]$Indent = ' ') {
|
||||
foreach ($p in $Object.PSObject.Properties | Where-Object { $_.Name -match $Pattern }) {
|
||||
$value = try { Format-Value $p.Value } catch { "<error: $($_.Exception.Message)>" }
|
||||
' {0} = {1}' -f $p.Name, $value
|
||||
'{0}{1} = {2}' -f $Indent, $p.Name, $value
|
||||
}
|
||||
$methods = @($Object | Get-Member -MemberType Methods -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.Name -match $LinkPattern } | ForEach-Object Name)
|
||||
if ($methods) { ' methods: ' + ($methods -join ', ') }
|
||||
Where-Object { $_.Name -match $Pattern } | ForEach-Object Name)
|
||||
if ($methods) { $Indent + 'methods: ' + ($methods -join ', ') }
|
||||
}
|
||||
|
||||
function Get-Prop($Object, [string]$Name) {
|
||||
@@ -147,6 +148,39 @@ $report = & {
|
||||
" ${cmd}: error: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
''
|
||||
|
||||
# The collector uses IsScheduleEnabled and ScheduleOptions.NextRun; show what else is there in
|
||||
# case this version keeps the next run somewhere different
|
||||
"== 5. Schedules (culture: $([Globalization.CultureInfo]::CurrentCulture.Name))"
|
||||
$SchedulePattern = 'Schedul|Next|Latest|Run|Enabled|Daily|Periodic|Monthly|Continuous|After|Option'
|
||||
foreach ($j in $jobs) {
|
||||
" $($j.Name) [$(Get-Prop $j 'JobType')]"
|
||||
Show-LinkMembers $j $SchedulePattern ' '
|
||||
foreach ($source in 'ScheduleOptions', 'GetScheduleOptions()', 'Get-VBRJobScheduleOptions') {
|
||||
try {
|
||||
$opts = switch ($source) {
|
||||
'ScheduleOptions' { $j.ScheduleOptions }
|
||||
'GetScheduleOptions()' { $j.GetScheduleOptions() }
|
||||
'Get-VBRJobScheduleOptions' { Get-VBRJobScheduleOptions -Job $j -WarningAction SilentlyContinue }
|
||||
}
|
||||
if ($null -eq $opts) { " ${source}: <null>"; continue }
|
||||
" ${source} ($($opts.GetType().FullName)):"
|
||||
foreach ($p in $opts.PSObject.Properties) {
|
||||
$value = try { $p.Value } catch { "<error: $($_.Exception.Message)>" }
|
||||
$type = if ($null -eq $value) { 'null' } else { $value.GetType().Name }
|
||||
if ($value -is [string] -or $value -is [ValueType] -or $null -eq $value) {
|
||||
' {0} ({1}) = {2}' -f $p.Name, $type, (Format-Value $value)
|
||||
} else {
|
||||
' {0} ({1})' -f $p.Name, $type
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
" ${source}: not available: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
''
|
||||
}
|
||||
} | Out-String -Width 300
|
||||
|
||||
$report
|
||||
|
||||
Reference in New Issue
Block a user