Feeding switch parameter from pipeline input

Welcome Forums General PowerShell Q&A Feeding switch parameter from pipeline input

This topic contains 8 replies, has 5 voices, and was last updated by

 
Participant
2 years, 11 months ago.

  • Author
    Posts
  • #33288

    Participant
    Points: 1
    Rank: Member

    Hello experts, I need to pass parameters to a script from pipeline input by importing the required values from CSV file. The original script has more than 15 parameters to be passed and input values are stored in a CSV file. I am posting a simple example to express the issue.

    Below are the contents of CSV file (Input.csv)

    ResourceGroupName,SetThrottling
    TestRG1,1
    TestRG2,0
    TestRG3,1
    TestRG4,0
    TestRG5,0

    Script file – Switch-FromPipelineTest.ps1

    [CmdletBinding()]
    Param
    (
    [Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
    [String]$ResourceGroupName,

    [Parameter(ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
    [Switch]$SetThrottling
    )

    Begin {}
    Process
    {
    Function TestingValues
    {
    Param
    (
    $ResourceGroupName,
    $SetThrottling
    )

    Write-Host "$ResourceGroupName is set to $SetThrottling"
    }

    TestingValues -ResourceGroupName $ResourceGroupName -SetThrottling $SetThrottling
    }
    End {}

    If I run the command Import-Csv .\Input.csv | .\Switch-FromPipelineTest.ps1 it gives an error as given below:

    C:\Scripts\Switch-FromPipelineTest.ps1 : Cannot process argument transformation
    on parameter 'SetThrottling'. Cannot convert value "System.String" to type
    "System.Management.Automation.SwitchParameter". Boolean parameters accept only
    Boolean values and numbers, such as $True, $False, 1 or 0.
    At line:1 char:26
    + Import-Csv .\Input.csv | .\Switch-FromPipelineTest.ps1
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (@{ResourceGroup...etThrottling=1}:P
    SObject) [Swith-FromPipelineTest.ps1], ParameterBindingArgumentTransformati
    onException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Switch-FromPi
    pelineTest.ps1

    In order to make this work, I have to run below command:
    Import-Csv -Path .\Input.csv -Verbose | Select-Object -Property ResourceGroupName,@{n='SetThrottling';e={[bool][int]$_.SetThrottling}} | .\Switch-FromPipelineTest.ps1

    Is there a way we can omit the type casting done by using custom property expression in the second command? as in the original script, I have several [switch] parameters and I need to do the same thing for each [switch] parameter.

  • #33290

    Participant
    Points: 0
    Rank: Member

    remove ValueFromPipeline=$True from both parameters
    and read some tips here
    Tips on Implementing Pipeline Support

    todo: move function TestingValues to begin{} block

  • #33291

    Member
    Points: 0
    Rank: Member

    Hmm, I've never tried to do a switch parameter from the pipeline. However, when you're using splatting, you can do switches with $true or $false, so maybe it'll work in the pipeline if you make it a [bool] instead of [int].

  • #33303

    Participant
    Points: 1
    Rank: Member

    @Max Kozlov: I went through that link earlier and also tried to remove ValueFromPipeline=$True from both parameters, it didn't help. I still need to manually convert the value from CSV column to [Switch] / [bool] before passing it to the script.

    @dave Wyatt: I can execute the script if I use:
    Import-Csv -Path .\Input.csv -Verbose | Select-Object -Property ResourceGroupName,@{n='SetThrottling';e={[bool][int]$_.SetThrottling}} | .\Switch-FromPipelineTest.ps1

    But I want to get rid of this extra layer of conversion using Select-Object, since my actual script has now around 30 parameters that I need to pass using CSV and there are many switch parameters that I have to convert like this if I don't get a solution.

  • #33304

    Participant
    Points: 0
    Rank: Member

    sorry, does not test solution before...
    also you need to change or remove parameter types from outer proxy function and do type conversion inplace
    this variant works well

    [CmdletBinding()]
     Param
     (
     [Parameter(Mandatory=$True, ValueFromPipelineByPropertyName=$True)]
     [string]$ResourceGroupName,
    
    [Parameter(ValueFromPipelineByPropertyName=$True)]
     [int]$SetThrottling
     )
    
    Begin {
     Function TestingValues
     {
     Param
     (
     [string]$ResourceGroupName,
     [switch]$SetThrottling
     )
    
    Write-Host "$ResourceGroupName is set to $SetThrottling"
     }
    }
     Process
     {
    	TestingValues -ResourceGroupName $ResourceGroupName -SetThrottling:([bool]$SetThrottling)
     }
     End {}
    
  • #33305

    Participant
    Points: 0
    Rank: Member

    btw, import-csv afaik always import values as string thus you always need conversion as you do with select, as I suggest with inplace conversion or by using foreach-object:

    Import-Csv -Path .\Input.csv -Verbose | Foreach-Object { $_.SetThrottling=[bool][int]$_.SetThrottling; $_ }  | .\Switch-FromPipelineTest.ps1
    

    if you need to convert many parameters you can do this in cycle like

    $toconvert = 'SetThrottling','param1','param2'
    
    Import-Csv -Path .\Input.csv -Verbose | Foreach-Object {
    foreach ($param in $toconvert) {
    $_.$param = [bool][int]$_.$param 
    }
    $_
    }  |
     .\Switch-FromPipelineTest.ps1
    
  • #33306

    Participant
    Points: 52
    Rank: Member

    As Max said, the main problem here is that Import-Csv makes all values from the CSV file as String values, and powershell obviously does not like trying to convert the string values to bool.

    I too would recommend just placing a Select-Object between your Import-Csv and your function with a calculated property to try to convert the property from the CSV file into a Boolean value. It may seem like unnecessary work but unfortunately it's due to the way the Import-Csv cmdlet was designed (to this point at least).

    PS Merry Christmas!!

  • #33310

    Participant
    Points: 1
    Rank: Member

    Thank you all for your inputs. After looking at all possibilities I think I have to convert the switch parameter to a string parameter by sung a validate set of "Yes" and "No". I will change the CSV format to use Yes and NO instead of 1 and 0.

    In script I will check the value using If condition whether $SetThrottling = Yes or No.

    That seems to be the only option for now as there is no other way we can pass Bool values through pipeline while importing CSV.

  • #33314

    Participant
    Points: 0
    Rank: Member

    (Post update: Scratch that, I see the problem and the below does not help the issue)

    @savindrasingh-shahoo use [System.Convert]::ToBoolean()

    https://social.technet.microsoft.com/Forums/windowsserver/en-US/300b5602-b16a-4a10-96fd-3e2e6ba29ed6/importcsv-with-true-and-false-values?forum=winserverpowershell

    [pscustomobject]@{
        Value1 = $true
        Value2 = $false
        Value3 = "string"
    } | Export-Csv test.csv
    
    $a = Import-Csv test.csv
    
    [System.Convert]::ToBoolean($a.Value1)
    [System.Convert]::ToBoolean($a.Value2)
    [System.Convert]::ToBoolean($a.Value3)
    
    ($a.Value1).GetType()
    ($a.Value2).GetType()
    ([System.Convert]::ToBoolean($a.Value1)).GetType()
    ([System.Convert]::ToBoolean($a.Value2)).GetType()
    

    Results:

    True
    False
    Exception calling "ToBoolean" with "1" argument(s): "String was not recognized as a valid Boolean."
    At line:11 char:1
    + [System.Convert]::ToBoolean($a.Value3)
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : FormatException
    
    IsPublic IsSerial Name                                     BaseType                                                                                                                  
    -------- -------- ----                                     --------                                                                                                                  
    True     True     String                                   System.Object                                                                                                             
    True     True     String                                   System.Object                                                                                                             
    True     True     Boolean                                  System.ValueType                                                                                                          
    True     True     Boolean                                  System.ValueType
    

The topic ‘Feeding switch parameter from pipeline input’ is closed to new replies.