Processing parameters in a function

I have written a simple function. It takes a computer name, and then in the Process {} block I use Invoke-Command to run an action on each machine. My parameter is created like this:
Param(
[Parameter(valuefrompipeline=$true,Position=0)]
[string]$ComputerName=$ThisServer,

So I can supply a single name, a list of names or get a list from the pipeline.
However, it appears that things get processed in different ways when they get to the Process{} block. A single name is OK, as is input from the pipeline. But a list of machine names fails. Is this because the list is an array, and this is handled differently? How do get round this in a simple way?

Thanks

Can you post the rest of your code? Just be sure to sanitize it so it doesn’t contain any private information. It would be useful to see what the Function actually does instead of just seeing the Parameter.

Here you go Ed, nothing special…

Function Stop-GEOService
{

[CmdletBinding()]
Param(
    [Parameter(valuefrompipeline=$true)]
    [string[]]$ComputerName=($servername.keys | %{if($servername.$_  -eq $env:computername){$_}})
    )
    Begin
    {
     "Preparing to stop service..."
    }
    Process
    {
        $geoServer= $($serverName[$($ComputerName)]) 
        "Processing: $ComputerName  System Name: $geoServer"
        try
        {
          Invoke-Command -ComputerName $geoServer { Stop-Service -DisplayName "GEO*" -Confirm} -ErrorAction stop
          Add-VSToolsLog -LogFile VSTools.log -LogText " services were stopped on $ComputerName"
        }
        Catch
        {
            Write-Host "An error occured"
            $errorMessage = $_.Exception.Message
            Write-Host $errorMessage
            Add-VSToolsLog -LogFile VSTools.log -LogText "An error occurred trying to Stop GEO services for $ComputerName, the error was $errorMessage"
        }
        }
    End
    {
    }

}

Thanks for your help.

SideNote: If you use the “pre” and “/pre” html tags around your code, it will put it in a pretty format like below, making it much easier t read in the post.

Here is an example of your issue.

Function Test {
    [CmdLetBinding()]
    Param(
        [Parameter(valuefrompipeline=$true)]
        [String[]]$ComputerName
    )
    Begin{}
    Process {
        Write-Host $ComputerName
    }
    End {}
}

$objects = @(
    [PSCustomObject]@{ComputerName = "Test1"; Date = (Get-Date).AddDays(-1)},
    [PSCustomObject]@{ComputerName = "Test2"; Date = (Get-Date).AddDays(-10)},
    [PSCustomObject]@{ComputerName = "Test3"; Date = (Get-Date).AddDays(-20)}
)

$objects | test
write-host "------------------------------------"
test -ComputerName $objects

Results:

@{ComputerName=Test1; Date=11/12/2015 08:21:25}
@{ComputerName=Test2; Date=11/03/2015 08:21:25}
@{ComputerName=Test3; Date=10/24/2015 08:21:25}
------------------------------------
@{ComputerName=Test1; Date=11/12/2015 08:21:25} @{ComputerName=Test2; Date=11/03/2015 08:21:25} @{ComputerName=Test3; Date=10/24/2015 08:21:25}

The reason for this difference is that when you are using the Pipeline, the Process{} script block acts like a foreach loop for the pipeline input, so each input object in processed one at a time. The Process{} block only does this for pipeline input. So when you pass the objects as a parameter, there is nothing looping through the objects individually to process them one at a time. Instead they are being processed as one single array of objects. Thus the result is different.

In order to handle multiple object as input by a parameter instead of via the pipeline, you need to add a foreach loop to the code like this.

Function Test {
    [CmdLetBinding()]
    Param(
        [Parameter(valuefrompipeline=$true)]
        [String[]]$ComputerName
    )
    Begin{}
    Process {
        ForEach ($Computer in $ComputerName) {
            Write-Host $Computer
        }
    }
    End {}
}

$objects = @(
    [PSCustomObject]@{ComputerName = "Test1"; Date = (Get-Date).AddDays(-1)},
    [PSCustomObject]@{ComputerName = "Test2"; Date = (Get-Date).AddDays(-10)},
    [PSCustomObject]@{ComputerName = "Test3"; Date = (Get-Date).AddDays(-20)}
)

$objects | test
write-host "------------------------------------"
test -ComputerName $objects

Results:
@{ComputerName=Test1; Date=11/12/2015 08:28:32}
@{ComputerName=Test2; Date=11/03/2015 08:28:32}
@{ComputerName=Test3; Date=10/24/2015 08:28:32}

@{ComputerName=Test1; Date=11/12/2015 08:28:32}
@{ComputerName=Test2; Date=11/03/2015 08:28:32}
@{ComputerName=Test3; Date=10/24/2015 08:28:32}

Great, thanks for the help.