1

I'm using the following to create a dynamic menu for repair jobs I'm running on remote servers:

Write-Host "`nCurrent Repair States:"
(Get-Job | Where-Object {$_.State -ieq 'Completed' -or $_.State -ieq 'Running' -and $_.Name -like "*-Repair"}) | Format-Table Name, State -HideTableHeaders

$jobList = Get-Job | Where-Object {$_.State -ieq 'Completed'-and $_.Name -like "*-Repair"}
Write-Host "Selectable Completed SCCM Client Repairs:`n"
Foreach ($menuItem in $jobList) {
    "  {0}.`t{1}" -f ($jobList.IndexOf($menuItem) + 1), $menuItem.Name
}

$jobChoice = ''
while ([string]::IsNullOrWhiteSpace($jobChoice)) {
    $jobChoice = Read-Host "`nPlease choose the Machine by number"
    if ($jobChoice -inotin 1..$jobList.Count) {
        Write-Host
        Write-Host ('    Please try again ...') -Foreground Yellow
        Write-Host
                
        $jobChoice = ''
    }
}

This works great as long as there are zero or two or more jobs that meet the Where-Object criteria. Though once there is only one item found I get the following error:

Method invocation failed because [System.Management.Automation.PSRemotingJob] does not contain a method named 'IndexOf'.
At C:\repairCheck.ps1:7 char:5
+     "  {0}.`t{1}" -f ($jobList.IndexOf($menuItem) + 1), $menuItem ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound
mklement0
  • 382,024
  • 64
  • 607
  • 775
kinaw
  • 25
  • 2
  • In short: When you collect command output in a variable, if only a _single_ object happens to be output, it is stored _as-is_. Only if _two or more_ objects are output is an _array_ (`[object[]]`) created. To ensure that what is collected is _always_ an array, use the array-subexpression operator, `$var = @(...)`, or an array cast / type constraint (e.g. `[array] $var = ...`), though note that PowerShell's unified handling of scalars and collections often makes that unnecessary. See [this answer](https://stackoverflow.com/a/60020105/45375) for background information. – mklement0 Oct 07 '21 at 17:14

1 Answers1

1

Change this statement:

$jobList = Get-Job | Where-Object {$_.State -ieq 'Completed'-and $_.Name -like "*-Repair"}

to:

$jobList = @(Get-Job | Where-Object {$_.State -ieq 'Completed'-and $_.Name -like "*-Repair"})

The array subexpression operator (@()) will ensure that the value assigned to $jobList is always an array, regardless of whether the Get-Job | ... expression evaluates to 0, 1 or multiple job references.

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206