Powershell中的选项菜单:继续循环后

时间:2018-02-08 17:19:04

标签: powershell

我想在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"

4 个答案:

答案 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"