Sam Porch
Sam Porch

Reputation: 771

Function-scoped variable in PowerShell (with Advanced Methods)?

Can someone please tell me what I'm missing here?

function Test-Cmdlet {
    [CmdletBinding()]
    Param (
        [string] $Prepend,
        [parameter(ValueFromPipeline=$true)] [string] $OtherString
    )

    BEGIN 
    {
        if ($Prepend -eq $null) {
            $Prepend = ".."
        }
    }

    PROCESS
    {
        write-host ($Prepend + $OtherString)
    }
}

# success:
PS> @( "ab", "cd" ) | Test-Cmdlet "-"
-ab
-cd

# failure:
PS> @( "ab", "cd" ) | Test-Cmdlet
ab
cd

# should be:
..ab
..cd

Why is $Prepend not getting set?

I've tried declaring variables outside the BEGIN/PROCESS blocks, but the interpreter doesn't accept that.

I've tried using: Set-Variable -Name "Prepend" -Value ".." -Scope 1 (and Scope 0, and Scope 2), instead of: $Prepend = "..", but still nothing works.

I'm familiar with $global:Variable, but any idea how to get function-scoped variables in a cmdlet with Advanced Methods?

Edit:

The solution, as per below, is:

function Test-Cmdlet {
    [CmdletBinding()]
    Param (
        [string] $Prepend,
        [parameter(ValueFromPipeline=$true)] [string] $OtherString
    )

    BEGIN 
    {
        $_prepend = $Prepend

        if (!$Prepend) {
            $_prepend = ".."
        }
    }

    PROCESS
    {
        write-host ($_prepend + $OtherString)
    }
}

Upvotes: 2

Views: 896

Answers (2)

Paul
Paul

Reputation: 5861

Because by defining $Prepend as a parameter an empty string is created so your if condition never applys. You can check for an empty string instead of checking for $null as an alternative.

Regards

Upvotes: 2

briantist
briantist

Reputation: 47792

I have to assume that you're using Powershell 2.0 for this. In that version, when you set the value of a parameter in the Begin block, it will not retain that value in the Process or End blocks.

This was changed in Powershell 3.0+.

For v2.0, assign a non-parameter variable the value of the parameter and use that throughout all 3 blocks:

function Test-Cmdlet {
    [CmdletBinding()]
    Param (
        [string] $Prepend,
        [parameter(ValueFromPipeline=$true)] [string] $OtherString
    )

    BEGIN 
    {
        if ($Prepend -eq $null) {
            $doPrepend = ".."
        } else {
            $doPrepend = $Prepend
        }
    }

    PROCESS
    {
        write-host ($doPrepend + $OtherString)
    }
}

Upvotes: 1

Related Questions