2

I am writing a function in PowerShell 3.0 . One parameter in the function should be set as mandatory depending on the value of another parameter.

The function declaratioin would be as following:

function removeVolumeandArrayFromHost(){
Param( [Parameter(mandatory = $true)] [ValidateSet('iSCSI','FC')] $arrayType, ##IpAddress/Name of the target host 
   [Parameter(mandatory = $true)] $volumeName, ##Name of the volume to be disconnected. (Volume name as in the array.)
   [Parameter(mandatory = $false)] $FCACL, ##Access control list name to which volume is added (Related to FC Array only)

   ## Work with the parameters given.
}

In the above function, The parameter '$arrayType' can have the value 'iSCSI' or 'FC'.

The parameter $FCACL should be mandatory(mandatory = $true) only if $arrayTpe = 'FC'. if $arrayType = 'iSCSI' then the $FCACL parameter should not be mandatory (mandatory = $false)

I tried using parametersetname but it dosent help as I need to lookinto the value of the parameter $arrayType to decide if $FCACL would be mandatory or not.

Any type of help or pointers would be highly appreciated.

Thanks a lot in advance. :)

user3543477
  • 615
  • 3
  • 13
  • 26
  • Usually in something like this, I'd write a begin/process/end, and in the beginning, I'd handle validation like this and Write-Error if it wasn't what I wanted. – Chris N Feb 01 '16 at 19:31
  • 1
    You need dynamic parameters for that. – user4003407 Feb 01 '16 at 19:37
  • I don't have time for a full answer but you can do this with [the `DynamicParam` keyword](http://www.powershellmagazine.com/2014/05/29/dynamic-parameters-in-powershell/). It's a bit of work though. The way @ChrisN advocates is often more straightforward. In both instances, if you're using the pipeline it may not work as expected so test thoroughly. – briantist Feb 01 '16 at 19:38
  • You can check out my answer from [this](http://stackoverflow.com/questions/30111408/powershell-multiple-parameters-for-a-tabexpansion-argumentcompleter/30114610#30114610) question for some info on how to work with dynamic parameters. – TheMadTechnician Feb 01 '16 at 19:48
  • To clarify, you don't want the $FCACL to be specified at all if iSCSI transport is used right? (FCACL wouldn't make sense in that case). – Χpẘ Feb 02 '16 at 00:17
  • @ChrisN: The begin/process helped me as I would be calling this function in other scripts and calling this function would not change dynamically depending on the type of array. Thanks a lot for your tip. :) – user3543477 Feb 02 '16 at 00:31
  • @briantist,@TheMadTechnician,@PetSerAl: Thanks for the info about Dynamic Parameters:) – user3543477 Feb 02 '16 at 00:32
  • @user3543477 I added this as an answer in the event that it helps someone else. – Chris N Feb 02 '16 at 14:31

3 Answers3

2

You can use Dynamic Parameters, or if you change your $arrayType variable to a switch, then you can use ParameterSetName to make things mandatory. So things become like this:

Function removeVolumeandArrayFromHost(){
Param( 
    [Parameter(ParameterSetName="FC")][switch]$FC,
    [Parameter(ParameterSetName="iSCSI")][switch]$iSCSI,
    [Parameter(ParameterSetName="FC",Mandatory=$true)] [string]$FCACL,

    [Parameter(mandatory = $true)] [string]$volumeName
)
....
   ## Work with the parameters given.
}

Or, if you know that you are only dealing with either FC or iSCSI, then you only really need one switch statement saying whether or not it is FC or not. If the -FC switch is present, then it will invoke the ParameterSetName=FC and require the -FCACL parameter. If you exclude the -FC switch, you assume it is iSCSI, and the ParameterSetName will make sure that you won't require -FCACL.

Function removeVolumeandArrayFromHost(){
Param( 
    [Parameter(ParameterSetName="FC")][switch]$FC,
    [Parameter(ParameterSetName="FC",Mandatory=$true)] [string]$FCACL,

    [Parameter(mandatory = $true)] [string]$volumeName
)
....
   ## Work with the parameters given.
}
HAL9256
  • 12,384
  • 1
  • 34
  • 46
  • I was about to suggest the same. You should add `[Parameter(ParameterSetName="iSCSI",Mandatory=$false)]` to `$FCACL`, though, since the parameter is supposed to be optional for the iSCSI parameter set if I understand the question correctly. – Ansgar Wiechers Feb 01 '16 at 20:29
  • @AnsgarWiechers Yeah you're right. I was thinking of adding that (for a complete solution it should be added), but I was guessing by the name "FC...ACL" that it was FC specific ;-) – HAL9256 Feb 01 '16 at 20:33
  • OP comments confirm that FCACL is FC specific. – Χpẘ Feb 02 '16 at 01:14
  • @HAL9256: Thankyou for the answer. Using the begin/process/end helped me in this case. Thanks for letting me know the concept of dynamic parameters, it would help me in the future :) – user3543477 Feb 03 '16 at 02:09
0

One option is to use the Begin / Process / End portions of the function and handle this kind of stuff in the "Begin" portion, instead of adding a Dynamic Parameter, as other answers have suggested.

Chris N
  • 7,239
  • 1
  • 24
  • 27
0

The suggestion given by Chris N worked perfectly in my case as I had to deal with only one parameter in this way. My understanding is that Dynamic parameters would be a better option if dealing with many such parameters.

I am adding the code here for much more clarity.

function removeVolumeandArrayFromHost(){
    Param( [Parameter(mandatory = $true)] [ValidateSet('iSCSI','FC')] $arrayType, ##IpAddress/Name of the target host 
       [Parameter(mandatory = $true)] $volumeName, ##Name of the volume to be disconnected. (Volume name as in the array.)
       [Parameter(mandatory = $false)] $FCACL) ##Access control list name to which volume is added (Related to FC Array only)       
    begin{
        if (($arrayType -eq 'FC') -and ($FCACL -eq $null)){
            Write-Error "For a FC Array, the FCACL parameter cannot be null."
            return
        }
    }
    process{
        .....
        .....
    }
}

Thankyou all for your inputs and suggestions. I appreciate your help.

user3543477
  • 615
  • 3
  • 13
  • 26