Using Switch

Tagged: 

This topic contains 12 replies, has 7 voices, and was last updated by Profile photo of Adnan Rashid Adnan Rashid 2 years, 5 months ago.

  • Author
    Posts
  • #16424
    Profile photo of Adnan Rashid
    Adnan Rashid
    Participant

    Hello,

    Please advise if this is possible

    $variable = "Do you want reboot computer 1, 2 or both? Type 1 or computerA, 2 or computerB, or 3 for computer A and B"

    Switch ($variable) {

    1 { Write-Output " Code will be here to reboot computerA" break}
    2 { Write-Output" Code will be here to reboot computerB" break }
    3 { # How do i call switch 1 and then switch 2 rather than rewriting everything in switch 1 and 2 into switch 3 }
    }

    The actual code i am writing is much bigger and because i'm struggling to find a way to call switch 1 and 2.. im having to duplicate work into switch 3 which seems very inefficient to me.

    Thanks for your help!

  • #16425
    Profile photo of Raymond Slieff
    Raymond Slieff
    Participant

    Maybe use a function, so the amount of code in each switch statement is minimal?

    Alternatively, just write the entire thing as a function that takes a string array and cycles through the ones provided?

    Otherwise I am not really sure this works for a switch statement, maybe two IFs fits this situation better. You could say IF 1 OR both, followed by IF 2 or Both.

  • #16427
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    The way you've structured the code, there's going to be some duplication either way (if nothing else, calls to the same function to reboot the computers.)

    However, if $variable were an array containing either 1, 2, or both 1 and 2, then this would work:

    switch ($variable) {
        1 { Write-Output " Code will be here to reboot computerA" }
        2 { Write-Output" Code will be here to reboot computerB" }
    }
    

    Note that you have to get rid of the "break" statements in order for this processing of an entire array to take place. Here's a more generic example demonstrating the results:

    $array = 1,2,4
    
    switch ($array)
    {
        1 { "Array contains 1" }
        2 { "Array contains 2" }
        3 { "Array contains 3" }
        4 { "Array contains 4" }
        5 { "Array contains 5" }
    }
    

    Edit: The forums are giving me a hard time for some reason; my closing quotes (whether single or double) keep showing up as HTML escape sequences.

  • #16428
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    One option is a prompt outlined here: http://windowsitpro.com/blog/asking-script-users-choice

    When you start asking more than simple yes\no questions or have to ask multiple questions to do a task, it's better to use a GUI interface IMHO. If you created a simple form and checkboxes for each computer with a Reboot button, then you could check 2 of 5 computers and the code is going to do something like foreach checkbox in form { if ($_.Checked -eq $true) {Restart-Computer $_.Value} }. You just need to make a determination if your scenario is complex enough to warrant a GUI. If you want to try a GUI option, you'll need Powershell Studio from Sapien Technologies or they have a deprecated free tool (you need to sign up, sign in and there is free tools folder in downloads if I recall correctly) and build the basic form. Powershell uses .NET forms and requires A LOT of code for a form, so a WYSIWYG interface will speed things along.

  • #16430
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    Using a question & and answer approaches works for a couple of machines but think about the possible combinations when you get to 5 machines! At 20 machines you don't even want to think about it.

    The suggestion of writing a function to do this is the better approach. Create the function so that it can accept an array of computer names. You can then use it like this:

    rebootcomputer -comp computera

    rebootcomputer -comp computer

    rebootcomputer -comp computera, computer

    rebootcomputer -comp computera, computer, computer

    if you have a lot of computers – put their names in a file then

    rebootcomputer -comp (get-content computers.txt)

    Forcing you scripts to be interactive negates one of the great advantages of automation – you don't need to touch it. having a file of computer names as input means I can schedule the reboots to occur overnight. Unless you're working the night shift you can't do that with an interactive script

  • #16431
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    [blockquote]rebootcomputer -comp computera

    rebootcomputer -comp computer

    rebootcomputer -comp computera, computer

    rebootcomputer -comp computera, computer, computer

    if you have a lot of computers – put their names in a file then

    rebootcomputer -comp (get-content computers.txt)[/blockquote]

    Also, just a side note, the [b]Restart-Computer[/b] cmdlet already exists and contains all of the functionality (and much more) that Richard shared. Just wanted to ensure it was mentioned before someone attempted to create a function for something that already is available.

  • #16432
    Profile photo of Adnan Rashid
    Adnan Rashid
    Participant

    Hello Guys,

    thanks for the input! I think i will go with the function method – my actual script is quite a large bit of code that needs to be resuable and i think a function might be the cleanest way.

    I will just need to work on parameterising the script so it can take various inputs and then translate 3 to mean calling function which i guess could be called from the switch so something like

    switch ($variable) {

    1 { function-A }
    2 { function-B }
    3 { function-A, function-B}

    }

    i'll give this a go and let you know how i get on – should work fine don't see any issues with this one.

    thanks for your advice everyone!

  • #16435
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    No – you're making it over complicated

    function reboot {
    param ( [string[]]$computername )

    foreach ($computer in $computername) {

    ## add code to reboot here
    }

    }

  • #16439
    Profile photo of Adnan Rashid
    Adnan Rashid
    Participant

    Hello!

    I won't be able to use the foreach reason being for each will cycle through each of the computers which is not what is desired.

    It should instead be – should computer A be restarted?
    – should computer B be restarted?
    – should computer A and B be restarted?

    I've tested the the function method and implemented like this

    $computer = read-host "which computer should restart? 1, 2 or 3 (3 for both)

    switch ($computer)

    1 { function-A ($computer) }
    2 { function-A {$computer) }
    3 {
    $computer = 1
    function-A

    $computer = 2
    function-A

    }

    Any alternatives / improvements on this? With foreach we have no control over which one's we want restarted right?

    By the way, this is not actually for a computer restart -the reason script is for creating shares on a VNX SAN – computer restart was just a example to use for the purposes of the idea because its essentially the same thing.

    thanks!

  • #16455
    Profile photo of Peter Jurgens
    Peter Jurgens
    Participant

    Yes foreach iterates through each item that has been passed through as input. Therefore, if you don't want something to apply, either filter it out, or don't include it in the input!! You're massively over complicating something that is as simple as:

    Restart-Computer Comp1
    

    OR

    Restart-Computer Comp2
    

    OR

    Restart-Computer Comp1,Comp2
    

    The above code accomplishes exactly what you're suggesting by using a switch statement, however it's done in just one line. The choice for the user is to input the name of the computer they want to restart.

  • #16457
    Profile photo of Simon Wåhlin
    Simon Wåhlin
    Participant

    Hi Adnan,

    As I understand the thread, restarting a computer is just an example and not at all what you actually want to do. You do want to display an interactive question and trigger one or several action(s) based on the answer.

    Assuming that is correct, you need to handle if the user gives an invalid answer and have a "default" action. Also an important thing to note about the switch statement is that any condition that is met will get executed. That being said you could either use Switch like you are using in your post above where the condition 1 only will trigger if the answer is exactly 1, or you could use the parameter -Regex for Switch. -Regex will treat each condition as a regular expression and if it matches the tested value, the scriptblock will execute.

    Here is an example where an invalid answer will trigger the question again and if the answer contains 'A', action A will get triggered. If the answer contains 'B', action B will get triggered. Answer 'AB' will result in both actions. A thing to have in mind here is that if a user enters 'abcdefg' (which might be considered an invalid answer), a and b will get triggered.

    $Question = "Which option would you like? (A,B or AB)"
    $KeepLooping = $true
    Do
    {
        $Answer = Read-Host -Prompt $Question
        Switch -Regex ($Answer) 
        {
            'A' 
            {
                Write-Verbose -Message 'Calling function A'
                # Type your action A here
                $KeepLooping = $false
            }
            'B' 
            {
                Write-Verbose -Message 'Calling function B'
                # Type your action A here
                $KeepLooping = $false
            }
            default 
            {
                Write-Warning -Message 'Unrecognized answer, please try again.'
            }
        }
    } While ($KeepLooping)
    
  • #16460
    Profile photo of Adnan Rashid
    Adnan Rashid
    Participant

    Hi Simon,

    You are spot on.

    That's interesting about the switch statement as I did not think about that at all. Instead I had a try and catch for any values beyond A and B following on from your example so people wouldn't be able to E or F.

    I think that method does accomplish what is necessary and also provides a fail safe too.

    Thanks! I'll let you know if i get any issues.

    Cheers,

    Adnan

  • #16461
    Profile photo of Adnan Rashid
    Adnan Rashid
    Participant

    Probably shouldn't have used the computer-restart as an example lol caused too much confusion – i'll keep that in mind next time 🙂

You must be logged in to reply to this topic.