Cannot use Switch condition in a function. What parameters get bind?

Welcome Forums General PowerShell Q&A Cannot use Switch condition in a function. What parameters get bind?

Viewing 5 reply threads
  • Author
    Posts
    • #198800
      Participant
      Topics: 2
      Replies: 10
      Points: 22
      Rank: Member

      I am writing a function to get users from Active Directory based on last name ‘like’, ‘equals’ or ‘UserID’ itself. For this if somehow got the code to work using IF statements but if I try the same approach (which I know is not correct) for Switch statement, I just cant seem to get it. I’ve been researching this for 2 weeks now and I am at the end of wits. To be fair, while researching I found out $PSCmdlet and ParameterSetName and $PSBoundParameters and I know if I use the Switch($PSBoundParameters.Keys) or $PSCmdlet.ParameterSetName . I guess I am asking for help to understand where I am going wrong in my basic understanding of the IF and the Switch statements.

      Here is the IF code that works

      Function Get-pcaUser {
      [CmdletBinding()]
      param (
      [Parameter()]
      [string] $like,

      [Parameter()]
      [string] $Equal,

      [Parameter()]
      [string] $ID
      )

      IF($like) {execute some code}
      IF($Equal) {execute some code}
      IF($ID) {execute some code}

      But if I try to use the switch in the same style, I can’t seem to get it to work.

      Switch ($like, $Equal, $ID){
      ($like) {execute some code}
      ($Equal) {execute some code}
      ($ID) {execute some code}
      }  or something like

      Switch ($like, $Equal, $ID){
      ($null -ne $like) {execute some code}
      ($null -ne $Equal) {execute some code}
      ($null -ne $ID) {execute some code}
      }

      What I am understanding incorrectly about the function parameter binding?

      To be fair, I already know I can use the switch like Switch($PSBoundParameter.Keys) and Switch($PSCmdlet.ParameterSetName)  and it works fine. I want to know why specifically this above code doesn’t work.

    • #198809
      Participant
      Topics: 12
      Replies: 1642
      Points: 2,660
      Helping Hand
      Rank: Community Hero

      Using $PSBoundParameter.Keys is the variable names, when you do Switch ($like, $Equal, $ID){ that is the variable values. Also, you may want to try a different approach to avoid calling the same cmdlet different ways. This example uses like, but if you don’t pass a wildcard it basically would return an exact match:

      Function Get-pcaUser {
          [CmdletBinding()]
          param (
      
              [Parameter(Mandatory=$true)]
              [string] $ID,
              [Parameter(Mandatory=$false)]
              [switch]$Exact
          )
          
          if ($Exact) {
              #Add asterisks to perform wildcard search
              $ID = '*{0}*' -f $ID
          }
          
          Get-ADUser -Filter {SamAccountName -like $ID}
          
      } 
      
      • #198884
        Participant
        Topics: 2
        Replies: 10
        Points: 22
        Rank: Member

        Hello Rob, thanks for taking the time to reply. I guess the key is what you mentioned, Using $PSBoundParameter.Keys is the variable names, when you do Switch ($like, $Equal, $ID){ that is the variable values.  I was trying to use the switch statement hoping to somehow match on the variables itself, but the way switch statement works is only when its passed a value to be evaluated on first. And then if the conditions match, the code block is executed.

        BTW, I really like the way you wrote your code in the window, what is this style a called. I tried to format the code but it didn’t come out the way yours did.

        Thanks .

    • #199040
      Participant
      Topics: 12
      Replies: 1642
      Points: 2,660
      Helping Hand
      Rank: Community Hero

      For what you were attempting to do, to execute code based on params, using the $PSBoundParameter.Keys is correct. However, that is not really how parameters are typically implemented in a function to execute code segments based on a single parameter. You should look through this forum or even look at blogs about functions to see how a normal function works.

      To format code you need to wrap it in the PRE tags, highlight the code and hit the PRE in the bar above.

    • #199154
      Participant
      Topics: 2
      Replies: 10
      Points: 22
      Rank: Member

      I did not look through the forums here but I scoured the internet and pretty much all the powershell books and I could barely find any examples of how to execute code segments in a function. Most of them suggest IF conditions, which works but I somehow hot stuck at this switch because its the PowerShell’s simplified IF/ ELSEIF/ END conditions.

      If you have any suggestions or links that you have seen are the better way to implement that, please share, I will read through and understand. Basically, I just want to understand and make my foundation strong, that is why even though I have found the ways to get my code to work, I am asking around to see if I am getting this correct. And looks like so far, the options are only limited to what I have found. 🙁

    • #199157
      Participant
      Topics: 2
      Replies: 10
      Points: 22
      Rank: Member

      Some of the links that really stuck with me are:

      https://4sysops.com/archives/powershell-advanced-functions-the-cmdletbinding-and-parameter-attribute/

      https://www.gngrninja.com/script-ninja/2020/1/19/using-psboundparameters-in-powershell

      I actually spoke to  GingerNinja and because I had him for so long on discord, he put all that he explained to me in a blog coz even he realized, there was not enough out there :). That was pretty cool.

      https://powershell.org/forums/search/using+switch+condition+in+functions/

      https://stackoverflow.com/questions/21528126/multiple-powershell-switch-parameters-can-it-be-optimized

      The last link is somewhat close, but not enough. A new idea non the less.

    • #199313
      Participant
      Topics: 12
      Replies: 1642
      Points: 2,660
      Helping Hand
      Rank: Community Hero

      There aren’t examples because that’s not an approach most people take. Let’s look at 2 examples:

      Function Get-ServiceWrapper {
          [CmdletBinding()]
          param (
      
              [Parameter(Mandatory=$false)]
              [string] $Name,
              [Parameter(Mandatory=$false)]
              [string]$ComputerName
          )
          
          switch ($PSBoundParameters.Keys) {
              'Name' {
                  Get-Service -Name $Name
              }
              'ComputerName' {
                  Get-Service -ComputerName $ComputerName
              }
          }
      } 
      

      With this example, there are many problems. First is that you only get one parameter, not both. I can’t call another computername AND look for a single name. The second is I’m calling the same command multiple times. Then there is this example:

      Function Get-ServiceWrapper {
          [CmdletBinding()]
          param (
      
              [Parameter(Mandatory=$false)]
              [string] $Name,
              [Parameter(Mandatory=$false)]
              [string]$ComputerName
          )
          
          $params = @{}
          #Basic check, if $Name is not NULL then add param
          if ($Name) {$params.Add('Name',$Name)}
          #Key Check, the ComputerName has to be passed to add param
          if ($PSBoundParameters.ContainsKey('ComputerName')) {$params.Add('ComputerName',$ComputerName)}
      
          #Command is called a single time
          Get-Service @params
      } 
      

      This approach we are building the parameters for the command dynamically and we can add any parameter to a single Get-Service call. Most of the example you see should be dynamically adding and removing command components with a hash table and splatting, which $PSBoundParameters is itself a hash table, so you can use it as a splat and it will pass the parameters directly to the command:

      Function Get-ServiceWrapper {
          [CmdletBinding()]
          param (
      
              [Parameter(Mandatory=$false)]
              [string] $Name,
              [Parameter(Mandatory=$false)]
              [string]$ComputerName
          )
          
          Get-Service @PSBoundParameters
      } 
      

      If you are trying to restrict commands parameters, there is built in functionality called parametersets that allow you to have logic that if you pass computername then you cannot pass name. Not sure what you background is from a programming\scripting, but you are probably not seeing examples because it’s not a proven approach.

Viewing 5 reply threads
  • The topic ‘Cannot use Switch condition in a function. What parameters get bind?’ is closed to new replies.