2

I played around with parameters and I ran into a problem.

function sign-script {
param(
    [Parameter(
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true,
        Position = 0,
        Mandatory = $true        
    )]
    [ValidateNotNullOrEmpty()]
    [Alias('FullName')]
    [string[]]$scripts,
    [string]$certname = "codesigning",
    [string]$certstore = "Cert:\LocalMachine\My"
)

Write-Host $scripts.count

}

If I run this function like this:

"Z:\test\test-sign.ps1","Z:\test\test-sign - Kopie (7).ps1" | sign-script

$scripts.count returns 1, instead of 2, why? Is the function not processing all values, or is it only accepting one value?

2 Answers 2

3

This is because you didn't split function body into blocks: begin, process and end.

  • begin block is executed before first item is arrived from pipeline
  • process block is executed for each item in pipeline
  • end block is executed after last item is recieved from pipeline.

If no blocks are defined, function body is implicitly set to end bblock. As the result, you will see only last item in pipeline. To fix that, I would suggest to rewrite the script as follows:

function sign-script {
param(
    [Parameter(
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true,
        Position = 0,
        Mandatory = $true        
    )]
    [ValidateNotNullOrEmpty()]
    [Alias('FullName')]
    [string[]]$scripts,
    [string]$certname = "codesigning",
    [string]$certstore = "Cert:\LocalMachine\My"
)
    process {
        Write-Host $scripts.count
    }
}

you just put the code that is supposed to process each item in pipeline into process block. When you run the script, you will see 1 twice, because process block is restarted for each item.

Sign up to request clarification or add additional context in comments.

Comments

2

Because you need a Process {} block to act on each item.

By default, with no Begin, End, or Process block, you only have an End, so you're only operating with the last item passed in.

function sign-script {
param(
    [Parameter(
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true,
        Position = 0,
        Mandatory = $true        
    )]
    [ValidateNotNullOrEmpty()]
    [Alias('FullName')]
    [string[]]$scripts,
    [string]$certname = "codesigning",
    [string]$certstore = "Cert:\LocalMachine\My"
)

Process {
    Write-Host $scripts.count
}

}

If you do it this way, you're going to see 1 returned twice. This is expected, because the process block gets called once per item.

Whereas if you call it like this:

sign-script "Z:\test\test-sign.ps1","Z:\test\test-sign - Kopie (7).ps1"

Then it will return 2.

The way I typically handle this is to use foreach in the process block:

Process {
    foreach ($script in $scripts) {
        Write-Host $script
    }
}

This ensures that you're always dealing with a single script in the innermost loop whether scripts were specified via pipeline or parameter.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.