mbourgon
mbourgon

Reputation: 1336

Script has two variables when done, but when I pipe to SELECT-object only first one returns data to console

I am trying to query multiple servers with WMI, but I don't always have access to the servers.

The code is below. Alas, it returns "access is denied" to the console, but I can't seem to get rid of it. Oh well.

However, I am trapping the servers that I can't connect to, so that I can tell someone else to look at them, or request access.

But when I run the code, it only returns the first list of servers; even if $failed_servers has values, nothing is returned. If I tell both to pipe to ogv, then two windows pop up.

Why won't both "$variable|select" work? If I remove the select on $failed_servers, then it shows up, albeit just sitting immediately underneath the successful ones. Which is okay-but-not-great.

$list = ("servera","serverb","serverc")
$failed_servers = @()
$final = foreach ($server_instance in $list)
{
$errors=@()
gwmi -query "select * from win32_service where name like '%SQLSERVER%'" -cn $server_instance -ErrorVariable +errors -ErrorAction SilentlyContinue
if ($errors.Count -gt 0) {$failed_servers += $server_instance
}
}

$final|select pscomputername, name, startmode, state |where {$_.pscomputername -ne $null}

$failed_servers |select @{N='Failed Servers'; E={$_}}

Upvotes: 4

Views: 905

Answers (2)

mklement0
mklement0

Reputation: 437803

What you're experiencing is merely a display problem:

  • Both your Select-Object calls produce output objects with 4 or fewer properties whose types do not have explicit formatting data associated with them (as reported by Get-FormatData).

  • This causes PowerShell's for-display output formatting system to implicitly render them via the Format-Table cmdlet.

  • The display columns that Format-Table uses are locked in based on the properties of the very first object that Format-Table receives.

  • Therefore, your second Select-Object call, whose output objects share no properties with the objects output by the first one, effectively produces no visible output - however, the objects are sent to the success output stream and are available for programmatic processing.

A simple demonstration:

& {
  # This locks in Month and Year as the display columns of the output table.
  Get-Date   | Select-Object Month, Year
  # This command's output will effectively be invisible,
  # because the property set Name, Attributes does not overlap with
  # Month, Year
  Get-Item \ | Select-Object Name, Attributes
}

The output will look something like this - note how the second statement's output is effectively invisible (save for an extra blank line at the end):


Month Year
----- ----
    9 2021


Note the problem can even affect a single statement that outputs objects of disparate types (whose types don't have associated formatting data); e.g.:
(Get-Date | Select-Object Year), (Get-Item \ | Select-Object Name)


Workarounds:

  • Applying | Format-List to the command above makes all objects visible, though that obviously changes the display format.

  • Intra-script you could pipe each Select-Object pipeline to Out-Host to force instant, pipeline-specific formatting, but - given that the results are sent directly to the host rather than to the success output stream - this technique precludes further programmatic processing.


Potential future improvements:

GitHub issue #7871 proposes at least issuing a warning if output objects effectively become invisible.

Upvotes: 5

Steven Woods
Steven Woods

Reputation: 11

I know this is old. However, since I stumbled upon this, I feel others may too.

Another solution to this display problem that may be more desirable, in some situations, would be to define a class ahead of time and then cast it.

class MyServiceClass {
    [string]$pscomputername
    [string]$name
    [string]$startmode
    [string]$state
}
# ... Code to Gather Results ...
[MyServiceClass[]]$final|select pscomputername, name, startmode, state |where {$_.pscomputername -ne $null}

I didn't test this with the OP's EXACT scenario but I did successfully use this for my own, similar situation. The beauty here is, you can enforce conformance to the data structure and also expand the class to include additional methods, etc.

Upvotes: 1

Related Questions