Switch Statement Not Processing all conditions: Check if OU Exists

89 Views Asked by At

I am attempting to use a switch to test different OUs for a matching location code OU which will cause a computer to moved to be moved into a child OU of the OUs I'm searching. A Location Code will only exist in one OU. So I'm checking to see if that OU exists via adsi.exists() which will return true when the location OU is found in each search location The problem is my switch seems to only evaluate the first condition and then moves on out of the switch. I'm not sure why this is happening, can anyone please advise?

What I expect: I expect each condition in the switch will be evaluate until one matches TRUE then the code associated with that match will be executed, moving my PC to the correct place in my directory.

Am I better served just doing if/else?

$LocationCode = $this.PCName.split("-")[0]
        
        try{
            $PCDC = (Get-ADComputer $this.PCName).DistinguishedName
            $FoundLCInOU = $true
            Switch ($FoundLCInOU) {
                # Check for location Code in Stores
                ([adsi]::Exists("OU DN")){
                    Write-Host " This computer belongs to the Location 1"
                }
                # Check for location code in CustomerExperienceCenter
                ([adsi]::Exists("OU DN")){
                    Write-Host "This Computer blongs to the Location 2"
                }
                # Check for location code in CAF
                ([adsi]::Exists("OU DN")){
                    Write-Host "This Computer Belongs to Location 3"
                }
                # Check for location code in HomeOffice 
                ([adsi]::Exists("OU DN")){
                    Write-Host "This computer belongs to the Location 4"
                }
            } catch {
                Write-Host "Couldn't find a home for this PC, just keep swimming..."
            }
1

There are 1 best solutions below

0
mklement0 On

Building on the comments, based on the current state of the code in your question:

  • The input to your switch statement is a static value, $true.

  • Your branch conditionals are all the same, ([adsi]::Exists("OU DN")).

  • In other words: you're not performing any operation related to the variable information stored in $LocationCode and $PCDC.

  • Generally, switch evaluates all branch conditionals, even after finding a match (the special Default branch is only executed if none of the other branches matched).

    • To stop further evaluation, use either continue or break:
    • break and continue work the same for single-value input (as in this case), but differ in meaning for array-valued input (see below for an example): continue moves on to the next array element, whereas break stops processing altogether.
  • Therefore, the behavior of your statement depends on the return value of the [adsi]::Exists() call: if $true, all branches are executed; if $false, none are.

  • Note that while using an expression such as your method call as a branch conditional works, the more flexible (albeit slower) approach is to use a script block { ... } inside of which you can refer to the input value at hand via the automatic $_ variable, call arbitrary commands, and output (what possibly implicitly evaluates to) $true or $false to signal a match or non-match; a simple example:

      # Note: Each element of the input array is processed separately.
      switch ('one', 'two', 'eight') { 
        # Matches inputs 'one' and 'two', but not 'eight'
        { $_.Length -eq 3 } { "Value is 3 chars. long: $_" }
      }
    
    • In other words:
      • Using an expression fundamentally works the same as using a literal in that the expression result must match the input value; e.g. with input 'foo', an example of an expression equivalent of a literal 'foo' conditional would be ('f' + 'oo')

      • By contrast, using a script block allows you to perform arbitrary operations and signal a match via a Boolean result.

        • If a given switch statement ends up having only script-block conditionals, it still offers some advantages over an equivalent if / elseif / else statement, namely:
          • switch's support for array-valued input (by implicitly processing each element) saves you from creating a loop explicitly.
          • A dynamically calculated input needn't be assigned to an aux. variable, given that switch makes the value available via the automatic $_ variable.

Not knowing your true requirements, here's an example of a more meaningful switch statement; for simplicity, it tests the $LocationCode value against known strings:

try {
  $PCDC = (Get-ADComputer -ErrorAction Stop $this.PCName).DistinguishedName
  $locationCode = $this.PCName.split('-')[0]
  switch ($locationCode) {
    'Stores' {
      'This computer belongs to the Location 1'
      continue  # short-circuit
    }
    'CustomerExperienceCenter' {
      'This Computer blongs to the Location 2'
      continue  # short-circuit
    }
    'CAF' {
      'This Computer Belongs to Location 3'
      continue  # short-circuit
    }
    # Check for location code in HomeOffice 
    'HomeOffice' {
      'This computer belongs to the Location 4'
      continue  # short-circuit
    }
    Default {
      Write-Warning "Unknown location code: $locationCode"
    }
  }
}
catch {
  Write-Warning "Couldn't find a home for this PC, just keep swimming..."
}

Note:

  • If your real intent is to extract the OU name from the computer's distinguished name and then test whether such an OU actually exists, you can use the techniques shown in this answer.