我想在PowerShell中创建一个简单的菜单。如果你看下我的例子,我正在等待,直到关键词' q'被压了。如果用户点击了' 1'或者' 2',它应该在switch中指定一些东西,离开循环并继续在脚本中显示"代码的另一部分"。
如果在开关中使用了break,它就不会离开循环。如果使用return is,则退出整个脚本。
以下是代码:
function Select-Machine
{
cls
Write-Host "1: Option1"
Write-Host "2: Option2"
Write-Host
}
Do{
Select-Machine
$input = Read-Host "Choose Virtual Machine"
switch ($input)
{
'1' {
#1: Do Something
break
}
'2' {
#2: Do Something
break
}
}
}until($input -eq 'q')
Write-Host "Another part of code"
答案 0 :(得分:3)
当您在break
中使用switch
语句时,您只能退出switch
(例如,它不会尝试评估任何其他选项)。您可以使用break
替换$input = 'q'
所在的位置,这将导致循环完成。
或者,您可以在切换后检查有效选项列表if
并在该点执行break
,然后在循环上运行。 E.g:
if ($input -in '1','2') { break }
答案 1 :(得分:1)
我要做的是使用Do/While
循环而不是Do/Until
循环。另外,将开关移到循环外部,不需要将它放在那里。
Do{
Select-Machine
$Response = Read-Host "Choose Virtual Machine"
}While($Response -notin 1,2,'q')
Switch($Response){
1 {
#Do 1 stuff!
continue
}
2 {
#Do 2 stuff!
continue
}
}
我已经在脚本中多次这样做了,我知道这些脚本将是交互式的并且有一个选项菜单。为此,我甚至编写了一个功能,为我制作体面的菜单:
Function MenuMaker{
param(
[parameter(Mandatory=$true)][String[]]$Selections,
[switch]$IncludeExit,
[string]$Title = $null
)
$Width = if($Title){$Length = $Title.Length;$Length2 = $Selections|%{$_.length}|Sort -Descending|Select -First 1;$Length2,$Length|Sort -Descending|Select -First 1}else{$Selections|%{$_.length}|Sort -Descending|Select -First 1}
$Buffer = if(($Width*1.5) -gt 78){[math]::floor((78-$width)/2)}else{[math]::floor($width/4)}
if($Buffer -gt 6){$Buffer = 6}
$MaxWidth = $Buffer*2+$Width+$($Selections.count).length+2
$Menu = @()
$Menu += "╔"+"═"*$maxwidth+"╗"
if($Title){
$Menu += "║"+" "*[Math]::Floor(($maxwidth-$title.Length)/2)+$Title+" "*[Math]::Ceiling(($maxwidth-$title.Length)/2)+"║"
$Menu += "╟"+"─"*$maxwidth+"╢"
}
For($i=1;$i -le $Selections.count;$i++){
$Item = "$(if ($Selections.count -gt 9 -and $i -lt 10){" "})$i`. "
$Menu += "║"+" "*$Buffer+$Item+$Selections[$i-1]+" "*($MaxWidth-$Buffer-$Item.Length-$Selections[$i-1].Length)+"║"
}
If($IncludeExit){
$Menu += "║"+" "*$MaxWidth+"║"
$Menu += "║"+" "*$Buffer+"X - Exit"+" "*($MaxWidth-$Buffer-8)+"║"
}
$Menu += "╚"+"═"*$maxwidth+"╝"
$menu
}
然后我可以这样称呼它:
MenuMaker -Selections 'SQL Server','Exchange Server' -Title 'Choose Virtual Machine' -IncludeExit
它会吐回来:
╔═══════════════════════════════════╗
║ Choose Virtual Machine ║
╟───────────────────────────────────╢
║ 1. SQL Server ║
║ 2. Exchange Server ║
║ ║
║ X - Exit ║
╚═══════════════════════════════════╝
要将其置于您的代码和我的建议的上下文中,它将如下所示:
Do{
cls
MenuMaker -Selections 'SQL Server','Exchange Server' -Title 'Choose Virtual Machine' -IncludeExit
$Response = Read-Host "Choose Virtual Machine"
}While($Response -notin 1,2,'x')
编辑:我刚刚意识到我的同时直到争论是毫无意义的,所有这一切都是将-in
翻转为-notin
。关键是你需要针对可能的选项验证他们的响应,而不仅仅是针对'q'。
答案 2 :(得分:0)
您可以使用break
标签从外圈跳出来。我不认为它特别漂亮,更好的是将until
条件变为真。但是我们走了。哦,请不要使用$input
变量名,这是PowerShell为em,输入保留的自动变量。
Write-Host "Begin"
:menu Do {
$i = Read-Host "Select"
switch ($i) {
'1' {
write-host "Do 1"
break menu
}
'2' {
write-host "Do 2"
break menu
}
}
} until($i -eq 'q')
Write-Host "End"
答案 3 :(得分:-1)
我认为您可以简化一下并删除功能:
Do{
#Select-Machine
write-Host "input 1 or 2 - Choose Virtual Machine"
if ($input = Read-Host "type in 1 or 2"){
switch ($input)
{
'1' {
#1: Do Something
Write-host '1 doing something'
break
}
'2' {
#2: Do Something
write-host '2 doing something'
break
}
}}
}until($input -eq 'q')
Write-Host "Another part of code"