为什么“退出”功能在我的 PowerShell 代码中不起作用?

时间:2021-05-18 20:28:39

标签: powershell

当我尝试“退出”功能时。它不会关闭控制台。它什么也不做。如何更改它以使其退出控制台?

Write-Host "-------------- MENU ---------------"
Write-Host "Utility Menu"
Write-Host "1 = Help Ipconfig"
Write-Host "2 = Ipconfig"
Write-Host "3 = Notepad"
Write-Host "4 = Calculator"
Write-Host "5 = Exit"
Write-Host "-----------------------------------"

$userinput = Read-Host "Please select a menu item: "

switch ( $userinput )
{
  1 {Help Ipconfig}
  2 {ipconfig}
  3 {start notepad}
  4 {start calc.exe}
  5 {Exit}
}

4 个答案:

答案 0 :(得分:3)

继续我的评论...

您的代码和菜单选择的 Gif

Execution

直接脚本运行您的代码不会对退出选项产生任何影响。将脚本重构为函数确实有效。

# Saved as Start-Menu.ps1
Function Start-Menu {
    Clear-Host

    Write-Host "-------------- MENU ---------------"
    Write-Host "Utility Menu"
    Write-Host "1 = Help Ipconfig"
    Write-Host "2 = Ipconfig"
    Write-Host "3 = Notepad"
    Write-Host "4 = Calculator"
    Write-Host "5 = Exit"
    Write-Host "-----------------------------------"

    $userinput = Read-Host "Please select a menu item: "

    switch ( $userinput )
    {
      1 {Help Ipconfig}
      2 {ipconfig}
      3 {start notepad}
      4 {start calc.exe}
      5 {Exit}
    }
}

关于动作的另一个 gif。

Using a function

或者使用 Colyn1337 给你的或者这个......

    switch ( $userinput )
    {
      1 {Help Ipconfig}
      2 {ipconfig}
      3 {start notepad}
      4 {start calc.exe}
      5 {Stop-Process -Id $PID}
    }

...(获取 PowerShell 会话的当前进程 ID),因此不需要该函数,只需按原样运行脚本,并注意命名空间的关闭速度比函数或 $PID 方法慢.

Using .Net Namespace

答案 1 :(得分:2)

现有答案中有有用的信息,但我觉得需要概念框架

<块引用>

exit [...] 它不会关闭控制台。

交互式脚本想要终止整个 PowerShell 会话(这会导致控制台窗口关闭)是不寻常的),并且 exit 只会在脚本之外执行此操作 - 有关详细信息,请参阅底部部分。

如果从脚本或函数中整体退出会话[1] 确实是您的意图,请使用 [Environment]::Exit(0),如 Colyn1337 所建议的那样。 (0 是用于报告进程终止的退出代码,按照惯例,它表示成功;关闭交互式会话时,此退出代码可能无关紧要。)


背景信息

Language keywords 用于从 PowerShell 退出各种范围

  • break 用于退出只是一个switch语句或一个< em>loop 语句 (foreach / for, while, do);也就是说,执行这样的语句之后在相同的范围内继续执行 - 请参阅概念性的 about_Break 帮助主题。

    • 陷阱:如果您使用 breakcontinue 没有封闭循环或 switch 语句,PowerShell 会查找调用为这样的语句堆栈并退出它找到的第一个这样的语句;如果没有,则终止当前调用堆栈;也就是说,至少封闭脚本作为一个整体终止。
      • 请注意,一个 ForEach-Object 调用(其内置别名是 %,有些令人困惑的是 foreach),总是在一个管道中,是不是一个循环;要“中断”传递给 ForEach-Object 的脚本块,即移动到下一个管道输入对象,使用 return
  • return 用于退出封闭的脚本文件(如果直接在脚本文件的顶级范围内执行)或functionscript block ({ ... }),可选择首先通过作为参数传递的表达式或命令输出数据 ;请参阅概念性的 about_Return 帮助主题。

    • return 对脚本报告的退出代码没有影响,因此可能对整个 PowerShell 进程产生影响;只有 exit 可用于设置退出代码 - 见下文。
  • exit 用于退出交互式会话封闭脚本文件 > 并可选择设置退出代码

    • 在脚本文件之外exit 退出交互式 PowerShell 会话作为一个整体(关闭控制台窗口)。

    • 在脚本文件内部exit 始终(仅)退出该脚本 - 即使从该脚本内的函数调用。< /p>

      • 注意与 return 的对比,它从函数中退出该函数,无论是否从脚本内部调用。
    • exit $exitCode - 其中 $exitCode 代表任何整数[2] - 可用于设置脚本/ 会话的退出代码;使用 just exitexit 0 相同:

      • 由于 PowerShell 的 error handling 不是基于退出代码(与 cmd.exebash 等 shell 不同),因此设置退出代码主要用于向外部调用者传达成功与失败的信息。

      • 如果您通过PowerShell的CLI(例如pwsh -File script.ps1)从外部执行脚本,通过exit $exitCode设置的退出代码也将成为进程< /em> 退出代码,外部调用者(例如 CI 工具)可以检查该代码。

        • 会话内部,由脚本通过 exit $exitCode 设置的退出代码反映在 automatic $LASTEXITCODE variable 中,但请注意,此变量也由对外部程序的任何调用设置,到该程序的进程退出代码。
      • 有关 PowerShell 中退出代码的相关性和使用的更多信息,请参阅 this post


[1] 正如 postanote's answer 所示,exit 来自一个 函数 内部,该函数已经点源(直接加载到)全局作用域,也退出整个会话。但是,最好使用 [Environment]::Exit(0) 明确表示退出整个会话的异常意图。

[2] 从技术上讲,您可以将任何表达式或命令传递给 exit(与 return 一样,尽管表达式/命令的输出变成了 数据,原样),但是任何至少不能转换为整数的东西——例如,exit 'not a number'——都被悄悄地忽略 em>exit 0 相同。另请注意,有效整数的范围因平台而异Windows 支持 [int] 值,即带符号的 32 位值,包括数字。相比之下,类 Unix 平台只支持无符号 [byte] 值,即从 0255 的数字(负数转换为正数,对于较大的值只考虑最低字节).

答案 2 :(得分:1)

Exit 命令实际上就像是 powershell 解析器中的一个函数。它周围有一些包装,当它执行时,Exit 并不总是意味着 Exit。它通常会被解析器替换为 Return

为了解决这个问题,您可以使用以下代码指示运行时终止:

[System.Environment]::Exit(0)

Exit 方法中的整数是您希望运行时在退出时输出的返回代码。通常,0 以外的任何值都将被解释为错误。

答案 3 :(得分:0)

使用 break 而不是 exit

Write-Host "-------------- MENU ---------------"
Write-Host "Utility Menu"
Write-Host "1 = Help Ipconfig"
Write-Host "2 = Ipconfig"
Write-Host "3 = Notepad"
Write-Host "4 = Calculator"
Write-Host "5 = Exit"
Write-Host "-----------------------------------"

$userinput = Read-Host "Please select a menu item: "

switch ( $userinput )
{
  1 {Help Ipconfig}
  2 {ipconfig}
  3 {start notepad}
  4 {start calc.exe}
  5 {break}
}