-1

I have a Powershell function where I am trying to declare some parameter $vipstatus, I mean when I try to execute the function with that parameter I want to see only the result stored in $vipstatus.

But when I try to execute that it's just listing out the entire output instead of the data stored in $vipstatus


function Get-NSVIPStatus
{
param(
    #[parameter(Mandatory=$false)]
    #[string]$vipstatus
)


$Components = @("virtualserver")

$VIPstatus = New-Object System.Collections.ArrayList($null)

foreach ($component in $Components) 
{
    $Metrics = Invoke-RestMethod "https://graphvip100.com/metrics/find?query=metrics.winops.netscalers.components.nsexsre*.$component.*.2m.status" -ErrorAction Stop
    $Raw = foreach ($metric in $Metrics) 
    {
        Invoke-RestMethod "https://graphvip100.com/render?target=$($metric.id)&from=-10min&format=csv" -ErrorAction Stop
    }

    $Data = $Raw | ConvertFrom-Csv -Header "Metric","Time","Value" | Where-Object { -not [string]::IsNullOrEmpty($_.Value) } | Group-Object -Property Metric

    foreach ($group in $Data) 
    {
        $NetscalerName = $group.Name.Split(".")[4]
        $Componentname = $group.name.split(".")[5]
        $Name          = $group.Name.Split(".")[6]
        
        If (($group.Group[-1].Value -eq "0.0") -and ($group.Group[-2].Value -eq "0.0") -and ($name -notmatch $exclusionpattern) -and ($netscalername -notmatch $netscalerexclusion))
        {
            $vipdown = [PSCustomObject]@{
                NetscalerName = $NetscalerName
                Componentname = $Componentname
                Name = $Name
        }
    
    foreach ($vip in $vipdown)
    {
        $null = $VIPstatus.Add($vipdown)
        write-warning "$vipdown is down"
    }      
            
     $failures = $true
        }
        ElseIf (($group.Group[-1].Value -eq "1.0") -and ($group.Group[-2].Value -eq "1.0") -and ($name -notmatch $exclusionpattern) -and ($netscalername -notmatch $netscalerexclusion))
        {
            Write-Verbose "$NetscalerName $Componentname $Name is UP" -Verbose
        }
        ElseIf (($group.Group[-1].Value -eq "2.0") -and ($group.Group[-2].Value -eq "2.0") -and ($name -notmatch $exclusionpattern) -and ($netscalername -notmatch $netscalerexclusion))
        {
            Write-Verbose "$NetscalerName $Componentname $Name is OUT OF SERVICE" -Verbose
        }
    }
}

So can anyone help me with what am I missing?

param( #[parameter(Mandatory=$false)] #[string]$vipstatus )

I want the output to be when executed "Get-NSVIPStatus $vipstatus" - 1,2,3

but it is listing out the entire scripts output

  • I don't think the issue is **how to declare Powershell parameter** but **how to specify the output**. Or do I completely miss the point and should the output go directly in `$vipstatus` of the current scope? (in that can you shouldn't reassign it with `$VIPstatus =` but have a parameter like: `Param( [Collections.Generic.List[String]]$vipstatus)` but I recommend against this). Please clarify your question using a [mcve], see also [how to ask](https://stackoverflow.com/help/how-to-ask) – iRon Jun 21 '23 at 13:40

1 Answers1

0

"I want the output to be when executed Get-NSVIPStatus $vipstatus - 1,2,3"

Output to were? To the pipeline or to the console?

In PowerShell there are multiple output streams, which includes a succes stream and an information stream. These two streams are separated streams but might appear quiet related as they eventually culminate in a single output to the console.

Regarding the pipeline (the success stream), objects might be:

  • passed on (piped) to a following cmdlet, e.g.:
  Write-Output "$manager exists in AD." |Next-Action
  • or assigned to a variable, e.g.:
  $result = Write-Output "$manager exists in AD."
  • or by default (in case they aren't piped or assigned), eventually displayed on the console

The streams are shared between all scopes, meaning that any command or (sub)function might put something on a specific stream.

Note

In the examples, I am explicitly using the Write-Output cmdlet but this cmdlet is usually not required as (said before) PowerShell sends any object that is not piped and not assigned down to the pipeline by default.

 

To explicitly write to the console you might use a different Write-* cmdlet along with Write-Host or Write-Information.

Note

Starting in Windows PowerShell 5.0, Write-Host is a wrapper for Write-Information This allows you to use Write-Host to emit output to the information stream. This enables the capture or suppression of data written using Write-Host while preserving backwards compatibility.

 

Your issue

Regarding your issue, there are several statements in your script that release objects to the pipeline, as e.g.:

Invoke-RestMethod "https://...

You might capture all this data (from the pipeline / success stream) in once in a new variable:

$Result = Get-NSVIPStatus $vipstatus

Or just purge it:

$Null = Get-NSVIPStatus $vipstatus

As you actually already doing for: $null = $VIPstatus.Add($vipdown)

Note

For the same reason, I would avoid using the ArrayList class in PowerShell as the Add method returns an [int] which will be dropped on the pipeline, instead use the List class: $VIPstatus = Collections.Generic.List[String]::new()

 

Leaving just all the other streams (initiated by Write-Warning, Write-Verbose, etc.) to end up on the console. which is probably not what you want, instead you probably want to be more specific to what you sent to the pipeline, for this the answer on Tracing where output is coming from in a Powershell script from mklement0 might be very helpful.

iRon
  • 20,463
  • 10
  • 53
  • 79