我正在嘗試撰寫一個帶有多個開關的 PowerShell 選單,但無法弄清楚為什么以前運行的命令會在退出時再次執行。任何幫助將不勝感激。我到目前為止的代碼如下:
function Show-Menu {
param (
[string]$Title = 'Menu'
)
Clear-Host
Write-Host "`n============= $Title =============`n"
Write-Host "Press 'A' to run all commands"
Write-Host "Press '1' to run foo"
Write-Host "Press '2' to run bar"
Write-Host "Press 'Q' to quit"
}
do {
Show-Menu
$Selection = Read-Host "`nPlease make a selection"
switch ($Selection) {
'A' {
$Actions = @('foo', 'bar')
}
'1' {
$Actions = "foo"
}
'2' {
$Actions = "bar"
}
}
switch ( $Actions ) {
'foo' {
Write-Host "foo executed"
Start-Sleep -Seconds 2
}
'bar' {
Write-Host "bar executed"
Start-Sleep -Seconds 2
}
}
}
until ($Selection -eq 'q')
uj5u.com熱心網友回復:
簡化。
與其將動作保存在變數中,然后再采取另一個步驟來評估該變數……執行動作。
不要使用回圈在單獨的位置檢查退出條件(即使用until),而是使用無限回圈和顯式break. 這有助于將邏輯保持在一個地方。
function foo { Write-Host "foo"; Start-Sleep -Seconds 1 }
function bar { Write-Host "bar"; Start-Sleep -Seconds 1 }
:menuLoop while ($true) {
Clear-Host
Write-Host "`n============= Menu =============`n"
Write-Host "Press 'A' to run all commands"
Write-Host "Press '1' to run foo"
Write-Host "Press '2' to run bar"
Write-Host "Press 'Q' to quit"
switch (Read-Host "`nPlease make a selection") {
'A' { foo; bar }
'1' { foo }
'2' { bar }
'Q' { break menuLoop }
}
}
您的方法無法正常作業,因為在您的代碼中,按下Q不會立即退出回圈,并且$Actions仍會從上次迭代開始填充。
這是另一個教訓:變數值不會在回圈中自行重置。始終$null在回圈開始時將變數設定為以獲得干凈的狀態。
注意:mainLoop標簽。沒有它,break將只適用于switch陳述句本身。見MSDN
話雖如此,PowerShell 有一個非常漂亮的內置選單系統,您可以使用它。
using namespace System.Management.Automation.Host
function foo { Write-Host "foo"; Start-Sleep -Seconds 1 }
function bar { Write-Host "bar"; Start-Sleep -Seconds 1 }
# set up available choices, and a help text for each of them
$choices = @(
[ChoiceDescription]::new('run &all commands', 'Will run foo, and then bar')
[ChoiceDescription]::new('&1 run foo', 'will run foo only')
[ChoiceDescription]::new('&2 run bar', 'will run bar only')
[ChoiceDescription]::new('&Quit', 'aborts the program')
)
# set up script blocks that correspond to each choice
$actions = @(
{ foo; bar }
{ foo }
{ bar }
{ break menuLoop }
)
:menuLoop while ($true) {
$result = $host.UI.PromptForChoice(
"Menu", # menu title
"Please make a selection", # menu prompt
$choices, # list of choices
0 # default choice
)
& $actions[$result] # execute chosen script block
}
在 PowerShell ISE 和常規 PowerShell 中運行它以查看它在每個環境中的行為。
uj5u.com熱心網友回復:
這是由于您的do...until回圈而發生的。您承諾在接受用戶輸入之前執行回圈。由于這種情況,$Actions已經從回圈的前一次迭代中設定,因此它運行先前運行的內容。
這意味著如果您不對$Actions回圈的每次迭代進行覆寫,其他命令也會發生這種情況。
對此的一個簡單解決方法是添加一個 case forq設定$Actions為不在 switch 陳述句評估中的內容$Actions。在這種情況下,應該使用空字串。
如果您也需要它以類似方式用于其他命令,而不是專門為設定案例q,您可以使用default案例來設定$Actions變數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/368901.html
上一篇:輸入框中的換行符?
