为什么我的PowerShell代码中的“退出”功能无法正常工作?

4
当我尝试使用“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 {Exit}
}

1
EXIT 关闭窗口,但仅当窗口是由启动脚本的操作打开的时才有效,例如右键单击脚本并选择“使用 PowerShell 运行”。我怀疑您打开了交互式控制台,并通过键入完整名称来启动脚本。在这种情况下,EXIT 关键字将不会关闭控制台窗口(那将是一个麻烦)。 - John Wu
3
尝试使用 [System.Environment]::Exit(0)。 (说明:这是一行 PowerShell 代码,用于退出当前进程并返回退出代码 0) - Colyn1337
4个回答

6

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

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

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

如果真正想要从脚本或函数[1]退出会话,则使用 [Environment]::Exit(0),如Colyn1337所建议。 (0 是要报告进程终止的退出代码,按照惯例表示成功;当关闭交互式会话时,此退出代码可能无关紧要。)


背景信息

PowerShell中用于退出各种作用域的语言关键字:

  • break 用于退出一个循环语句(foreach/forwhiledo)或者仅限于一个switch 语句。也就是,执行会在这样的语句之后继续在同一范围内进行 - 参见about_Break主题。

    • 陷阱:如果你使用 breakcontinue 没有包含循环或 switch 语句,PowerShell 会查找调用堆栈以找到这样的语句并退出第一个找到的语句; 如果不存在,则当前调用堆栈终止;也就是说,至少将整个封装脚本终止。
      • 请注意,一个 {{link2:ForEach-Object} 调用(其内置别名为:% 和有些令人困惑的 foreach),无论如何都不是循环;要从传递给 ForEach-Object 的脚本块中“退出”,即转到下一个管道输入对象,请使用 return
  • return 用于退出包含它的脚本文件(如果直接在脚本文件的顶级范围内执行)或者 函数脚本块 ({ ... }),可选地通过作为参数传递的表达式或命令输出数据来退出 (例如: return'foo');请参阅有关about_Return的概念性帮助主题。

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

    • 脚本文件之外,exit以整体方式退出交互式 PowerShell 会话(关闭控制台窗口)。

    • 脚本文件内部,exit总是仅退出该脚本(即使从该脚本内的一个函数中调用)。

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

      • 由于 PowerShell 的 错误处理不是基于退出代码(不像


        [1]正如 postanote的回答所示,在点操作(直接加载到)全局作用域中的函数内部使用exit会退出整个会话。但更好的方式是通过[Environment] :: Exit(0)显式地表示退出整个会话的异常意图。

        [2] 从技术上讲,你可以将任何表达式或命令传递给exit(就像return一样,尽管表达式/命令的输出在那里成为数据),但任何不能至少被转换为整数的东西 - 例如exit 'not a number' - 都会被静默忽略,并且与exit 0相同。还要注意,有效整数的范围因平台而异Windows支持[int]值,即包括负数的32位有符号值。相比之下,类Unix平台只支持无符号[byte]值,即从0255的数字(负数转换为正数,并且对于较大的值,仅考虑最低字节)。


4

继续我的评论...

您的代码和菜单选择的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


我见过的最优雅的答案!你是如何制作这样的屏幕动画的??? - adamt8
1
感谢'adamt8'。至于Giffing的事情,我使用一个叫做ScreenToGif的工具多年来制作所有我的演示或实验室演示,当我教授课程时。以前我使用另一个叫做'Demomate'的工具来进行“点击穿透”演示/实验室,但它已经不再被制作/发布了,尽管开发它的公司仍然存在。 - postanote

2
Exit 命令实际上类似于 PowerShell 解析器内的一个函数。它有一些包装,当执行时,Exit 并不总是意味着退出。通常情况下,解析器会将其替换为 Return
为了避免这种情况,您可以使用以下代码指示运行时终止: [System.Environment]::Exit(0) Exit 方法中的整数是您想要运行时输出的返回代码。通常,除 0 外的任何代码都将被解释为错误。

1
感谢您将评论中的解决方案发布为答案;+1 个赞,因为这是一个有效的解决方案,但 exit 关键字的使用方式不太正确(请参见我的答案了解详情)。 - mklement0

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}
}

1
“break”是退出“switch”语句的正确语句,但是OP想要关闭当前控制台窗口,即退出当前(PowerShell)进程。 - mklement0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接