$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.
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.
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:
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.
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:
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
Also, just a side note, the Restart-Computer 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.
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
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.
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.
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)
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.