0

I'm trying to write 2 functions:

  • the first one (Get-Lab) retrieves a [Lab] object
  • the second one (remove-Lab) remove a [Lab] object

[Lab] is a class defined in my module.

When a run Get-Lab I correctly retrieve my lab instance with the correct type : enter image description here

When I run Remove-Lab -Lab (Get-Lab -Name Mylab), the operation is correctly performed: enter image description here

But when I try to pass the [Lab] object through the pipeline it fails.

enter image description here

The function does not receive the object through the pipeline. However I've set the -Lab Parameter as mandatory with ValueFromPipeline=$true.

Function Remove-Lab{
[CmdletBinding(DefaultParameterSetName='Lab')]
param (
    [Parameter(ValueFromPipeline=$true,ParameterSetName='Lab',Position=0,Mandatory=$true)]
    [Lab]
    $Lab,
    
    # Parameter help description
    [Parameter(Position=1,Mandatory=$false)]
    [switch]
    $Force=$false
)

begin {
    Write-host ("`tLabName : {0}" -f $Lab.Name) -ForegroundColor Yellow

    if ($null -ne $Lab) {
        $LabToRemove = $Lab
    }

    if (-not [string]::IsNullOrEmpty($LabId)) {
        $LabToRemove = Get-Lab -Id $LabId
    }

    if (-not [string]::IsNullOrEmpty($Name)) {
        $LabToRemove = Get-Lab -Name $Name
    }

    if ($null -eq $LabToRemove) {
        throw "There is no Lab with specified characteristics. Please check your input"
    }
}

process {
    $DoRemoval = $true
    if ($Force.IsPresent -eq $false) {
        while ($null -eq $UserInput -or $UserInput -notin @('Y','N')) {
            $UserInput = Read-HostDefault -Prompt "Are you sure want to remove the selected Lab and all its components ? [Y]es, [N]o" -Default 'N'

            if ($UserInput -eq 'N') {
                $DoRemoval = $false
            }
        }

        Write-Host ("`tUser Input : {0}" -f $UserInput) -ForegroundColor Green
    }

    if ($DoRemoval -eq $true) {
        Write-Host ("`tAbout to Remove the following Lab : {0}" -f $LabToRemove.Name) -ForegroundColor Green
    }
}

end {

}

}

As you can see below when a debug this function, the $Lab Parameter is null. enter image description here

Do you have any idea about this issue ?

3
  • Maybe silly, but did you try to add the value of Get-Lab to a variable and pipe that variable to Remove-Lab. To be honest, I have not done it myself ever, but maybe your Get-Lab function is not 'pipable'. Commented Mar 8, 2021 at 12:44
  • You can't access pipeline input in begin, $Lab won't be available until it hits the process block Commented Mar 8, 2021 at 13:02
  • @Alex_P : already tried but not a solution. The solution was presented by Matthias Commented Mar 8, 2021 at 13:23

2 Answers 2

1

Since the function is testing on $LabId or $Name, these variables need to exist in the function and at the moment they do not. Try changing the parameters to:

[CmdletBinding(DefaultParameterSetName='LabId')]
param (
    [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName = $true, ParameterSetName='LabId',Position=0,Mandatory=$true)]
    [string]$LabId,

    [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName = $true, ParameterSetName='LabName',Position=0,Mandatory=$true)]
    [string]$Name,

    # Parameter help description
    [switch]$Force  # no need to set a switch to $false because if you don't send that param, the undelying value will be $false by default
)

Then remove

Write-host ("`tLabName : {0}" -f $Lab.Name) -ForegroundColor Yellow

if ($null -ne $Lab) {
    $LabToRemove = $Lab
}

Important part here is the ValueFromPipelineByPropertyName = $true declaration

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

Comments

0

begin runs before anything else, including pipeline parameter binding - so you need to move code that inspects a pipeline-bound parameter (like $Lab) to the process block:

Function Remove-Lab{
[CmdletBinding(DefaultParameterSetName='Lab')]
param (
    [Parameter(ValueFromPipeline=$true,ParameterSetName='Lab',Position=0,Mandatory=$true)]
    [Lab]
    $Lab,
    
    # Parameter help description
    [Parameter(Position=1,Mandatory=$false)]
    [switch]
    $Force=$false
)

process {
    Write-host ("`tLabName : {0}" -f $Lab.Name) -ForegroundColor Yellow

    if ($null -ne $Lab) {
        $LabToRemove = $Lab
    }

    if (-not [string]::IsNullOrEmpty($LabId)) {
        $LabToRemove = Get-Lab -Id $LabId
    }

    if (-not [string]::IsNullOrEmpty($Name)) {
        $LabToRemove = Get-Lab -Name $Name
    }

    if ($null -eq $LabToRemove) {
        throw "There is no Lab with specified characteristics. Please check your input"
    }

    $DoRemoval = $true
    if ($Force.IsPresent -eq $false) {
        while ($null -eq $UserInput -or $UserInput -notin @('Y','N')) {
            $UserInput = Read-HostDefault -Prompt "Are you sure want to remove the selected Lab and all its components ? [Y]es, [N]o" -Default 'N'

            if ($UserInput -eq 'N') {
                $DoRemoval = $false
            }
        }

        Write-Host ("`tUser Input : {0}" -f $UserInput) -ForegroundColor Green
    }

    if ($DoRemoval -eq $true) {
        Write-Host ("`tAbout to Remove the following Lab : {0}" -f $LabToRemove.Name) -ForegroundColor Green
    }
}

4 Comments

Thanks a lot for your quick answer. By moving the parameter inspection in the process block, it works.
@Régis You're welcome! Take note of Theo's answer as well - if you want to fall back to $Name or $LabId, you should declare them with separate parameter set names
@Régis One more thing: directly calling a blocking input function (like Read-HostDefault) in the middle of a pipeline is generally a bad idea - implement proper ShouldProcess and confirmation impact support if you want something like this :-)
OK. Thanks for your advices. I'm going to read your link with attention. bye ;-)

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.