【问题标题】:How do you do a ‘Pause’ with PowerShell 2.0?如何使用 PowerShell 2.0 进行“暂停”?
【发布时间】:2022-01-13 14:15:17
【问题描述】:

好吧,我输了。 PowerShell 让我很烦。我希望出现一个暂停对话框,但它不会。

PS W:\>>> $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Exception calling "ReadKey" with "1" argument(s): "The method or operation is not implemented."
At line:1 char:23
+ $host.UI.RawUI.ReadKey <<<< ("NoEcho")
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException

【问题讨论】:

  • 我在 PowerShell ISE 中遇到了同样的问题。不过在标准 PowerShell 控制台中工作正常。
  • 我只是在搞弄 powershell,即使 2 1/2 年后它仍然很烦人!
  • 如果您阅读 Adam's Tech link@Michael Sorens answer 中的代码(我在 2020 年写这篇文章时大约在页面的一半),您可能会发现一种将停顿包裹在 if (!$psise) { &lt;# pause #&gt; } 中的技术。如果您像我一样,并且想要暂停的 99% 的原因是您可以在屏幕闪烁之前阅读它,那么这将有所帮助,因为如果您在 ISE 中,它不会闪烁而您不会'不需要暂停

标签: powershell


【解决方案1】:

为了清楚起见,我认为值得回顾/总结这里的选择...然后提供我认为提供最佳实用程序的新变体。

ReadKey (System.Console)

write-host "Press any key to continue..."
[void][System.Console]::ReadKey($true)
  • 优点:接受任何键,但正确排除 Shift、Alt、Ctrl 修饰键。
  • 缺点:在 PS-ISE 中不起作用。

读取密钥(RawUI)

Write-Host "Press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
  • 缺点:在 PS-ISE 中不起作用。
  • 缺点:不排除修饰键。

cmd

cmd /c Pause | Out-Null
  • 缺点:在 PS-ISE 中不起作用。
  • 缺点:首次使用时会明显启动新的外壳/窗口;后续使用时不明显,但仍有开销

读取主机

Read-Host -Prompt "Press Enter to continue"
  • 优势:在 PS-ISE 中工作。
  • 缺点:只接受 Enter 键。

ReadKey 复合

这是上述 与从Adam's Tech Blog 提案中提取的 ISE 解决方法/kludge 的组合(由本页早期 cmets 的 Nick 提供)。我对后者做了两个细微的改进:添加了 Test-Path 以避免在您使用 Set-StrictMode 时出现错误(您这样做,不是吗?!)和最后的 Write-Host 在您的击键后添加一个换行符以放置提示在正确的地方。

Function Pause ($Message = "Press any key to continue . . . ") {
    if ((Test-Path variable:psISE) -and $psISE) {
        $Shell = New-Object -ComObject "WScript.Shell"
        $Button = $Shell.Popup("Click OK to continue.", 0, "Script Paused", 0)
    }
    else {     
        Write-Host -NoNewline $Message
        [void][System.Console]::ReadKey($true)
        Write-Host
    }
}
  • 优点:接受任何键,但正确排除 Shift、Alt、Ctrl 修饰键。
  • 优势:在 PS-ISE 中工作(尽管只能通过 Enter 或鼠标单击)
  • 缺点:不是单线!

【讨论】:

  • 最佳答案,尤其是因为它提供了适用于任何地方的解决方案
  • 很好的答案!我想指出,将 AllowCtrlC 参数添加到选项 2 允许用户在不终止脚本的情况下单击 Ctrl + C。尽管如此,这个选择仍然不能正确地排除 Ctrl 修饰键。 (就像用户只点击 Ctrl 键一样)参考:Microsoft TechNet - Windows PowerShell Tip: Press Any Key to Continue
  • 选项 3 和 5 还有一个缺点:在 linux 上不起作用
  • @bitbonk 如果您在 Linux 中工作......为什么选择 PowerShell?只是为什么?使用 Bash。
  • 因为我不想维护多个脚本,每个操作系统一个。一个适用于 Mac、Linux 和 Windows 的脚本就足够了,在我的例子中是 powershell。
【解决方案2】:
cmd /c pause | out-null

(这不是 PowerShell 方式,但它更优雅。)

保存树木。使用单线。

【讨论】:

  • /c 执行字符串指定的命令,然后终止 | out-null 将输出通过管道传输到 out-null,您将永远看不到它 如果您想看到“按任意键继续...”消息,请移除管道。此外,这似乎不适用于 PowerShell ISE。该过程只是卡住了,您无法按任何键。有什么办法吗?
  • @Wouter 查看这篇博文:How to Properly Pause a PowerShell Script
  • @Nick 是的,用 47 行代码替换“cmd /c pause | out-null”,听起来像是 PowerShell 方式。
  • @BillK 我链接到的帖子回答了 Wouter 的问题。你不同意吗?
  • 这不是对您的回答的评论,我认为您是完全正确的。这是对 PowerShell 的评论。我有点反感——自从我用 Cobol 编程以来,我还没有见过这么多毫无意义的模糊冗长。
【解决方案3】:

我假设您想从控制台读取输入。如果是这样,请使用Read-Host

【讨论】:

  • 同上 - 也许添加从下面窃取的提示文本.. Read-Host -Prompt "Press Enter to continue"
  • 出于某种原因不会为我暂停。我在 .bat 脚本中调用 powershell。
【解决方案4】:

cmd /c pause 之类的解决方案会导致新的命令解释器在后台启动和运行。虽然在某些情况下可以接受,但这并不理想。

使用Read-Host 的解决方案强制用户按Enter,并不是真正的“任何键”。

此解决方案将为您提供真正的“按任意键继续”界面,并且不会启动新的解释器,这将基本上模仿原始的 pause 命令。

Write-Host "Press any key to continue..."
[void][System.Console]::ReadKey($true)

【讨论】:

  • 技术上 ISE 超出了范围,因为最初的问题只询问了 Powershell 2.0 并排除了 ISE。如果您使用的是 ISE,则只需使用断点即可。
  • 1.我不同意 ISE 超出范围,但现在无关紧要。 2. 我注意到在 ISE 中无法帮助路人解决这个问题。
【解决方案5】:

除了Michael Sorens'回答:

在新进程中读取密钥

Start-Process PowerShell {[void][System.Console]::ReadKey($true)} -Wait -NoNewWindow
  • 优点:接受任何键但正确排除 Shift、Alt、Ctrl 修饰键。
  • 优势:在 PS-ISE 中工作。

【讨论】:

  • 这个很好用,但是会弹出一个新的powershell窗口,除非添加了-NoNewWindow :)
  • @jeuxjeux20,感谢您的建议,我已将此添加到答案中的命令中。
【解决方案6】:

在使用ReadKey 之前,您可能希望使用FlushInputBuffer 丢弃任何错误输入到控制台的字符,尤其是对于长时间运行的操作:

Write-Host -NoNewLine 'Press any key to continue...'
$Host.UI.RawUI.FlushInputBuffer()
$Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') | Out-Null

【讨论】:

    【解决方案7】:

    10 年后我来到这里.... 不知道从什么时候开始,但“暂停”在 PowerShell 中的工作方式与在 DOS 命令行中一样。

    【讨论】:

      【解决方案8】:

      如果你想为按下任意键添加计时器,这在 PS 5.1 中有效:

       $i=1
       while (
                       !([Console]::KeyAvailable) -and 
                       ($i -le 10)
                  ) {
                 sleep 1
                 Write-Host “$i..” -NoNewLine
                 $i++
       }
      

      请注意,c# $Host.UI.RawUI 的 KeyAvailable 方法目前在 PS 2 或 3 之后的许多 PS 版本中存在错误。

      【讨论】:

        【解决方案9】:

        Michael Sorens' answer 中选项 中的 PS-ISE 单线:

        [Void][Windows.Forms.MessageBox]::Show("Click OK to continue.", "Script Paused")
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-12
          • 1970-01-01
          • 1970-01-01
          • 2022-08-22
          • 1970-01-01
          • 1970-01-01
          • 2020-10-10
          • 1970-01-01
          相关资源
          最近更新 更多