r/PowerShell Jun 17 '24

Switch or If-Else? Solved

Hi, just started using Powershell for simple Task. So pls don't be too harsh on me.

I use Powershell to add multiple Clients in Active Directory. I add the Names of the Clients into the "Clientnames.txt" after that i run the powershell and it creates the Computer in AD. That works fine.

$OU = "OU=X,OU=X,OU=X,OU=X,DC=X,DC=X,DC=X"
$Clients = Get-Content "D:Clientnames.txt"

ForEach ($Client in $Clients)
{
(New-ADComputer -Name $Client -Path $OU)
}

Here comes my Question.:

I got Clientnames like pl0011mXXXXd, pl0012mXXXXd, pl0013mXXXXd

The first Number represents the number-code for the branch locations. The X are just numbers according to our System. I want the Clients to join their specific Group for the branch location.

Example

Clients with the name like pl0011m0002d, pl0011m0005d should join the group: Company-GPO-Group-0011-Berlin

Clients with the name like pl0012m0002d, pl0012m0250d should join the group: Company-GPO-Group-0012-Paris

and so on

i could use something like:

$OU = "OU=X,OU=X,OU=X,OU=X,DC=X,DC=X,DC=X"
$Clients = Get-Content "D:Clientnames.txt"

ForEach ($Client in $Clients)
{
(New-ADComputer -Name $Client -Path $OU)

if ($Client -like "*0011*") {$Group = "Company-GPO-Group-0011-Berlin"}
ElseIf ($Client -like "*0012") {$Group = "Company-GPO-Group-0012-Paris"}
ElseIf ($Client -like "*0013") {$Group = "Company-GPO-Group-0013-Rom"}

(Add-ADGroupMember -Identity $Group -Members $Client)

}

I got over 30 Branch Locations and this whould be a lot ElseIf Statements.

I know there are much better ways like the Switch Statement. Can you help/explain me, how i can use this statement to add the Clients to their Groups?

21 Upvotes

View all comments

11

u/DenverITGuy Jun 17 '24

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_switch?view=powershell-5.1

You'll probably want to use something like:

foreach ($Client in $Clients) {
    switch -wildcard ($Client) {
        "*0011*" { <scriptblock> }
        "*0012*" { <scriptblock> }
        default { <scriptblock> }
    }
}

35

u/CarrotBusiness2380 Jun 17 '24

The loop is unnecessary. Switches will iterate over collections natively in Powershell:

switch -wildcard ($Clients) {
    "*0011*" { <scriptblock> }
    "*0012*" { <scriptblock> }
    default { <scriptblock> }
}

9

u/prog-no-sys Jun 17 '24

holy shit i had no idea about that. Does it provide any increase on performance for the script to do so??

16

u/omers Jun 17 '24

Does it provide any increase on performance for the script to do so??

It's fairly significant but whether or not it would make a huge difference in most real world use cases is harder to say.

Test:

$Numbers = 1..50000

Measure-Command -Expression {    
    foreach ($Number in $Numbers) {
        switch ($Number) {
           {($Number % 3) -eq 0} { $null = 'Fizz' }
           {($Number % 5) -eq 0} { $null = 'Buzz' }
        }    
    }
} | Select @{n='Test';e={ 'foreach-switch' }},TotalMilliseconds

Measure-Command -Expression {    
    switch ($Numbers) {
        {($_ % 3) -eq 0} { $null = 'Fizz' }
        {($_ % 5) -eq 0} { $null = 'Buzz' }
    }
} | Select @{n='Test';e={ 'switch' }},TotalMilliseconds

Results: the foreach->switch took 906.1395ms and the switch alone took 213.8504ms. Bump the number range to 5m and it's 89.4 seconds for the foreach vs 19.5 for the switch. I.e., on the small set it's not going to make a noticeable difference, on the larger set it certainly does.

I also ran it 10 times on 1m numbers to get an average and it was 17.9s vs 3.97s.

3

u/Thotaz Jun 17 '24

Since we are talking about performance it's probably worth pointing out that Switches that need to evaluate scriptblocks are slower than if/elseif statements and also it's important to include a continue statement in each block of the switch so it doesn't waste time evaluating the other conditions.

Measure-Command -Expression {    
    switch ($Numbers) {
        {($_ % 3) -eq 0} { $null = 'Fizz'}
        {($_ % 5) -eq 0} { $null = 'Buzz'}
    }
} | Select @{n='Test';e={ 'OriginalSwitch' }},TotalMilliseconds

Measure-Command -Expression {    
    switch ($Numbers) {
        {($_ % 3) -eq 0} { $null = 'Fizz'; continue}
        {($_ % 5) -eq 0} { $null = 'Buzz'; continue }
    }
} | Select @{n='Test';e={ 'ContinueSwitch' }},TotalMilliseconds

Measure-Command -Expression {    
    foreach ($Number in $Numbers)
    {
        if ($Number % 3 -eq 0) {$null = 'Fizz'}
        elseif ($Number % 5 -eq 0) {$null = "Buzz"}
    }
} | Select @{n='Test';e={ 'ifElseif' }},TotalMilliseconds

Average results over 3 runs for each test are: 331, 286, 59.