Home > Software engineering >  How to get PowerShell Function to accept multiple parameters for multiple variables
How to get PowerShell Function to accept multiple parameters for multiple variables

Time:08-16

I just can't seem to figure out how to make my Function accept multiple parameters correctly.

I have a Function called Get-AdvAppReport. It does a whole lot of data collection and generates a report. This Function is part of a much larger script.

Inside Function Get-AdvAppReport, I have the following Parameters:

[CmdletBinding()]
        Param
        (
            [parameter(Mandatory = $false, ValueFromPipeline = $True)]
            [string[]]$ComputerName = $env:COMPUTERNAME.ToUpper(),
            [parameter(Mandatory = $false, ValueFromPipeline = $True)]
            [string[]]$ServType = ("COM").ToUpper(),
            [parameter(Mandatory = $false, ValueFromPipeline = $True)]
            [string[]]$SiteSize = ("STANDARD").ToUpper(),
            [parameter(Mandatory = $false, ValueFromPipeline = $True)]
            [string[]]$User = (Read-Host -prompt "Input User Name:  ")
        )

In the main script, I have multiple options, one of which is to generate a report based on the active connection, which has the above variables already defined. To call it, I'm calling with the following code:

Get-AdvAppReport $Computer $ServType $SiteSize

It works fine, the report runs and all is well.

What I'm trying to do is have this also work with an Imported CSV file.

At the top of the main script, I have a variable as:

$PROD_Serv = Import-CSV ".\Servers_PROD.csv"

And to try and call this method, in the script, I am using the following command:

Get-AdvAppReport $($PROD_Serv).ComputerName $($PROD_Serv).ServType $($PROD_Serv).SiteSize

If there is only one line within the CSV, it all works fine. On-screen, I have an output showing all is good with the variables.

singleserverworking

But if there are multiple lines in the CSV, i.e. as the following:

multiCSV

Then it doesn't work correctly because the second set of parameters is loaded all at once.

For example, the on-screen output shows the following:

multiserverfail

So it will process the first set of Parameters ($ComputerName) one at a time, but for each of those, it will try to use all of the $ServTypes in the CSV at once.

I've tried so many different ways, and just cannot figure out the logic to make PowerShell accept multiple parameters for multiple variables. I've been banging my head about this for a few days now, and am stuck.

Anyone have any idea how I can make a function work with multiple parameters and multiple variables? I just am not understanding why my logic is wrong and have searched high and low, and have not come up with a solution that works for a scenario the same as my current issue.

Edit: As requested, here is a chunk of the body of the script (sorry, lots of fluff for the report formatting using PS Module PSWriteHTML):

    New-HTMLMain -BackgroundColor "#241e69" {
                    
                    foreach ($Computer in $ComputerName)
                    {
                        $Computer = $Computer.ToUpper()
                        
                        Write-Color "`n`nApp Report for ", "$Computer ", "as Type ", "$ServType ", "Initiated...`n`n" -Color Magenta, Cyan, Magenta, Green, Magenta
                        
                        New-HTMLTab -TabName ($Computer   "_"   $ServType) -IconBrands microsoft  {
                            New-HTMLTabOptions -SelectorColor "#707cf1" -SelectorColorTarget "#383392" -Transition -LinearGradient -BorderRadius "10px" -FontSize "15" -FontWeight Bolder -FontFamily "Arial"
                            New-HTMLTableStyle -TextAlign center
                            If (Test-Connection -ComputerName $computer -Count 1)
                            {
                                Write-Color "`n     $Computer ", "ONLINE.     `n" -Color Cyan, Green
                                Add-Content $LogFile -Value "`n$($Timestamp.Invoke())  -  $Computer ONLINE"
                                
                                try
                                {
                                    Write-Color "`n     $Computer ", "App Report Data Collection ", "In Progress...     `n" -Color Cyan, White, Green
                                    Add-Content $LogFile -Value "`n$($Timestamp.Invoke())  -  $Computer App Report Data Collection Initiated"
                                    
                                    Get-AdvAppPreReport
                                    
                                    $spacer
                                    $spacer
                                    $spacer
                                    New-HTMLText -Text "End of Report" -Color "#f56e78" -fontsize 20 -Alignment Center -FontWeight Bolder -FontFamily Arial
                            }
                                
                                
                                catch
                                {
                                    Write-Warning "`n$($Timestamp.Invoke())  -  $Computer Ping Status error encountered.  -  $($_.Exception.Message)"
                                    Write-Color "`n     $Computer ", "Offline.     `n" -Color Cyan, Red
                                    New-HTMLText -Text "$Computer Offline."
                                    Add-Content $LogFile -Value "`n$($Timestamp.Invoke())  -  $Computer Offline."
                                }
                            }
                            Else
                            {
                                Write-Warning "`n$($Timestamp.Invoke())  -  $Computer Ping Status error encountered.  -  $($_.Exception.Message)"
                                Write-Color "`n     $Computer ", "OFFLINE.     `n" -Color Cyan, Red
                                
                                Add-Content $LogFile -Value "`n$($Timestamp.Invoke())  -  $Computer Offline."
                                
                                OfflineLog
                            }
                        }
                    }
                }

And then that Get-AdvAppPreReport Function is basically, If $ServType = DB, then perform these other data collection functions, ElseIF $ServType = WEB, then perform these other function, etc.

CodePudding user response:

Expanding on the comments, you're passing three parallel arrays into your function, equivalent to:

Get-AdvAppReport `
    -ComputerName @( "SERV01",   "SQL01", "MGMT01" ) `
    -ServType     @( "NTIER",    "DB",    "COM" ) `
    -SiteSize     @( "STANDARD", "LARGE", "STANDARD" )

You're then iterating over the $ComputerName array with something similar to:

foreach( $computer in $ComputerName )
{
    write-host "App Report for $computer as Type $ServType Initiated..."
}

and getting the output:

App Report for SERV01 as Type NTIER DB COM Initiated...
App Report for SQL01 as Type NTIER DB COM Initiated...
App Report for MGMT01 as Type NTIER DB COM Initiated...

The problem is that inside your foreach loop, you're expecting $ServType to contain just the item in the matching position in the second parameter, which isn't how a foreach loop works.

What you need to do instead is something like:

for( $i = 0; $i -lt $ComputerName.Length; $i   )
{
    write-host "App Report for $($ComputerName[$i]) as Type $($ServType[$i]) Initiated..."
}

and then your output will be:

App Report for SERV01 as Type NTIER Initiated...
App Report for SQL01 as Type DB Initiated...
App Report for MGMT01 as Type COM Initiated...

However you've now got potential issues if the parallel arrays aren't actually parallel - e.g. one of them is $null or a different length, so you might want to consider passing in an array of "report rows" instead:

function Get-AdvAppReport {
    param( [object[]] $ReportRows )
    foreach( $row in $ReportRows )
    {
        write-host "App Report for $($row.ComputerName) as Type $($row.ServType) Initiated..."
    }
}

Then, you can simply pass your converted csv object in:

$PROD_Serv = Import-CSV ".\Servers_PROD.csv"

Get-AdvAppReport -ReportRows $PROD_Serv

As an aside, your original code works when there's only one row because you're doing this:

Get-AdvAppReport `
    -ComputerName @( "SERV01" ) `
    -ServType     @( "NTIER" ) `
    -SiteSize     @( "STANDARD" )

and the entire $ServType array is just a single item so it appears to be working correctly when your original foreach loop runs, but logically it still suffers from the same problem.

CodePudding user response:

Maybe try something like this it's stupid but it might work.

Try puting in another For Loop like

$a=Import-CSV -Path "<.\path to your file>"

ForEach ($i in $a)
{

Get-AdvAppReport $($i).ComputerName $($i).ServType $($i).SiteSize

}

This is just something i thought off of top of my head. Might not work but keep me posted. You can moderate it and filter through it with IF just use $i.ServType or any of those cause $i will be one of the lines that is in queue in For Loop.

  • Related