掌握 PowerShell 暂停:命令行与脚本技术

有许多原因可以暂停脚本执行。也许脚本需要等待用户输入,减缓执行速度,或在继续之前等待另一个进程的完成。与PowerShell中的大多数任务一样,有多种方法可以暂停脚本。根据您要完成的任务,您选择的暂停方法将有其优势和劣势。为可用选项添加另一个复杂性的是PowerShell的新跨平台能力。由于PowerShell通常被用作”粘合”不同技术的方式,就像在Windows中一样,Linux命令行也有其用于暂停执行的选项,这些选项也可以并入PowerShell。

PowerShell暂停的方法

有哪些不同的方法可以暂停脚本执行?在本文中,我们将把暂停的能力分为本机和非本机命令。通过本机,我们指的是那些是PowerShell或.NET内置函数或方法。非本机方法被定义为特定于Windows和Linux的程序,可以与PowerShell一起使用。

本机方法

  • Start-Sleep
  • [System.Threading.Thread]::Sleep()
  • Read-Host
  • [Console]::ReadKey()
  • $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

非本机方法

Windows

  • pause
  • timeout

Linux

  • sleep
  • read -p

如你所见,有许多不同的选项,每个选项都有其利弊。你使用哪个选项将影响到执行被暂停的方式以及该暂停可能带来的其他效果。

本地方法

首先,我们将开始概述本地方法,因为它们在脚本中被最广泛使用。

Start-Sleep

最常用的暂停命令是远远超过其他的,Start-Sleep。这个命令接受两个简单的输入,即-Seconds-Milliseconds。秒可以是System.Double数值,而毫秒只能是System.Int32值。通过组合这两者,可以精确控制暂停的长度。Start-Sleep也有一个别名sleep

Start-Sleep -Seconds 2 -Milliseconds 300

在 PowerShell 6.2.0 之前,你不能写一个像2.3这样的小数秒值,这与我们在上面的代码中暂停的时间长度相同。从 6.2.0 开始,支持小数值,因此你现在可以写成:-Seconds 2.3

重要的是要注意,你可以通过使用Ctrl-C来跳出Start-Sleep函数。但并非所有方法都是这样!

线程休眠

A less commonly used method of pausing execution is the [System.Threading.Thread]::Sleep() .NET method. By passing in a System.Int32 or a TimeSpan value, this allows pausing of the current thread for a set amount of time. For example, to pause by that same amount of time, 2.3 seconds, as in our Start-Sleep example, we can write:

[System.Threading.Thread]::Sleep(2300)

要使用 Thread Sleep 方法与 TimeSpan 构造,您可以按以下步骤操作:

[System.Threading.Thread]::Sleep([TimeSpan]::New(0, 0, 0, 2, 300))

要无限期暂停线程,您可以使用 [System.Threading.Timeout]::InfiniteTimeSpan,但请记住这可能会锁定您的进程。

Start-Sleep 不同,Thread Sleep 方法不允许您使用 Ctrl-C 中断休眠例程。根据您的应用程序,这可能更可取。

关于线程休眠的另一个重要知识点是,它不能确保精确的时间。所有线程休眠都保证至少等待那么多秒。由于线程休眠计数与时钟滴答声相符,因此其他程序可能会中断此暂停功能,并强制等待时间更长。

虽然线程休眠有其用途,但由于这些问题,最好使用其他内置方法之一。

Read-Host

上述方法描述了暂停执行的方式,但仅适用于一段固定的时间。暂停执行的另一种方法是提示用户输入。使用此方法,必须执行手动操作,但要求确认以继续并可能包含其他输入非常有用。

Read-Host 是提示用户输入的最常见方式之一。通过提示用户输入,结果可以保存供代码进一步使用,或在需要时暂停执行。

Read-Host -Prompt "Press any key to continue"

一旦输入文本,需要按下回车键或返回键继续执行。通过这样做,并且不将输入保存到变量中,将会将输入的相同文本输出到控制台。

Press Enter to Move Execution Along

如果要将输入的结果文本保存到变量以供以后使用,只需将Read-Host输入分配给变量即可。

$Input = Read-Host -Prompt "Press any key to continue"

有时您可能希望将输入的结果文本读取为安全字符串。幸运的是,Read-Host使这变得非常容易。

$SecureInput = Read-Host -Prompt "Enter your password" -AsSecureString

Ctrl-C将允许您跳出Read-Host提示。

控制台 ReadKey 方法

使用[Console]::ReadKey()方法,您可以轻松读取键命令,以及修饰符,同时暂停程序执行。默认情况下,发送的键命令将作为System.ConsoleKeyInfo对象回显到屏幕。这包括KeyKeyCharModifiers值,当检查某些键组合时非常有用。

[Console]::ReadKey()
Console ReadKey Command

通常您可能希望在不断进行之前检查某个特定的键输入。这可以通过像下面这样使用Do-While循环轻松完成。

Do {
	$Key = [Console]::ReadKey($True)
	Write-Host $Key.Key
} While ( $Key.Key -NE [ConsoleKey]::Escape )
Do-While Loop Key

请注意,由于我们正在寻找特定的键组合,Ctrl-C不会退出此处的输入。

主机 RawUI ReadKey 方法

最后,我们有$host.UI.RawUI.ReadKey()方法。这类似于控制台的ReadKey方法,但此方法允许传入其他选项以控制行为并进一步输出。

$host.UI.RawUI.ReadKey()
RawUI.ReadKey

有许多ReadKeyOptions可传入,这可能会使RawUI ReadKey方法更有用。

  • AllowCtrlC
  • IncludeKeyDown
  • IncludeKeyUp
  • NoEcho

可以按以下方式使用此方法,该方式包括按键按下事件并且不会将文本回显出来。

$host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')

此方法将允许使用Ctrl-C中断命令,除非使用了AllowCtrlC选项。

非本机方法

在此部分中,我们探讨了一些暂停脚本执行的非本机方法。这些方法旨在利用非PowerShell控制台特定实用程序,这些实用程序可以根据您的需求集成到PowerShell脚本中。

Windows

暂停

暂停命令非常简单,会显示按任意键继续. . .并保持该状态,直到按下键盘上的任意键以继续执行。

cmd /c 'pause'
Pause Command

您可能会问如何在脚本中使用这个命令,但就像您使用其他命令一样,在您的脚本中插入cmd /c 'pause'命令来利用本地功能。

Cmd/C Pause Command

超时

通常用于Windows批处理文件,超时命令允许暂停指定的秒数,并可选择忽略任何按键命令。即使超时时间尚未过去,用户按键通常也会继续执行。通过传入秒数非常简单地使用它。

# 暂停 2 秒
timeout /t 2

# 暂停 5 秒但不允许按键中断
timeout /t 5 /nobreak

# 无限期暂停直到按键按下
timeout /t -1
Timeout Command

pause命令一样,在脚本中插入timeout命令,在下面的示例中,我们按下回车键来继续。

Timeout Command Execution

Linux

睡眠

像Windows中的pause命令一样,Linux中的sleep命令允许设置睡眠的任意值。与暂停命令不同,sleep命令有更多的选项,可以灵活设置睡眠时间。

sleep 2.3s
Sleep Command

sleep 命令还可选择性地具有后缀,可允许定义更长的时间段。例如:

  • sleep 1m – 睡眠一分钟
  • sleep 2h – 睡眠两小时
  • sleep 1d – 睡眠一天

阅读 -P

最后,Linux 暂停的另一种方式是使用 read 应用程序暂停,等待按下回车键继续执行。还有一个可选的超时参数,如果在指定时间内没有按下回车键,将继续执行。

read -p 'Press enter to continue' -t 5
Read Application to Pause

结论

如您所见,有许多方法可以在脚本或命令行中暂停执行。根据您的需求,它可以是简单的 Start-Sleep 命令,也可以是更复杂的输入驱动过程。结合本地命令,PowerShell 暂停可以在几乎任何环境中实现灵活性,并实现脚本的最大效用。

Source:
https://adamtheautomator.com/powershell-pause/