只是想知道是否可以通过按 escape 在 while 循环中转义读取主机。
我尝试过执行 do-else 循环,但它只能识别读取主机外部的按钮按下操作。
这基本上就是我所拥有的
#Import Active Directory Module
Import-Module ActiveDirectory
#Get standard variables
$_Date=Get-Date -Format "MM/dd/yyyy"
$_Server=Read-Host "Enter the domain you want to search"
#Request credentials
$_Creds=Get-Credential
while($true){
#Requests user input username
$_Name=Read-Host "Enter account name you wish to disable"
#rest of code
}
如果我想更改域名,我希望能够转义它
使用
Read-Host
您无法执行此操作,但您可以考虑使用图形输入对话框而不是在控制台中进行提示。毕竟,Get-Credential
cmdlet 还显示 GUI。
如果您可以选择,可以使用以下方法来完成:
function Show-InputBox {
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true, Position = 0)]
[string]$Message,
[string]$Title = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.PSCommandPath),
[string]$defaultText = ''
)
Add-Type -AssemblyName 'Microsoft.VisualBasic'
return [Microsoft.VisualBasic.Interaction]::InputBox($Message, $Title, $defaultText)
}
while($true) {
$_Name = Show-InputBox "Enter account name you wish to disable"
if ([string]::IsNullOrWhiteSpace($_Name)) {
# the box was cancelled, so exit the loop
break
}
# proceed with the rest of the code
}
如果用户按下Esc键,单击Cancel,或者将输入留空,则可以退出while循环,否则继续执行代码。
我编写了这个对我有用的函数。
# Returns the string "x" when Escape key is pressed, or whatever is indicated with -CancelString
# Pass -MaxLen n to define max string length
function Read-HostPlus()
{
param
(
$CancelString = "x",
$MaxLen = 60
)
$result = ""
$cursor = New-Object System.Management.Automation.Host.Coordinates
while ($true)
{
While (!$host.UI.RawUI.KeyAvailable ){}
$key = $host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown")
switch ($key.virtualkeycode)
{
27 { While (!$host.UI.RawUI.KeyAvailable ){}; return $CancelString }
13 { While (!$host.UI.RawUI.KeyAvailable ){}; return $result }
8
{
if ($result.length -gt 0)
{
$cursor = $host.UI.RawUI.CursorPosition
$width = $host.UI.RawUI.MaxWindowSize.Width
if ( $cursor.x -gt 0) { $cursor.x-- }
else { $cursor.x = $width -1; $cursor.y-- }
$Host.UI.RawUI.CursorPosition = $cursor ; write-host " " ; $Host.UI.RawUI.CursorPosition = $cursor
$result = $result.substring(0,$result.length - 1 )
}
}
Default
{
$key_char = $key.character
if( [byte][char]$key_char -ne 0 -and [byte][char]$key_char -gt 31 -and ($result + $key_char).Length -le $MaxLen )
{
$result += $key_char
$cursor.x = $host.UI.RawUI.CursorPosition.X
Write-Host $key_char -NoNewline
if ($cursor.X -eq $host.UI.RawUI.MaxWindowSize.Width-1 ) {write-host " `b" -NoNewline }
}
}
}
}
}
您无法使用
Read-Host
执行此操作,但您可以通过 PSReadLine
模块(Windows 10 / Windows Server 2016 上的 Windows PowerShell 版本 5 或更高版本附带)和 PowerShell Core)及其 PSConsoleHostReadline
函数来执行此操作:
重要:
从 PSReadLine v2.2.6 开始,下面的解决方案是 hack,因为
PSConsoleHostReadline
仅支持提示 PowerShell 语句,而不支持开放式用户输入。
该黑客应该适用于您的情况,因为您提示输入的用户名应该是语法上有效的 PowerShell 语句。
但是,支持任意输入是有问题的,原因有两个:
将应用不适用的语法着色 - 但是,您可以暂时将所有可配置颜色设置为相同颜色,但这会很麻烦。
更重要的是,如果输入恰好是语法上不完整的PowerShell语句,
PSConsoleHostReadline
将不会接受输入,而是继续提示(换行);例如输入a|
就会导致这个问题。
还有:
无论提交什么输入,都会添加到命令历史记录中。
虽然您当前可以在退出脚本时删除临时安装的键盘处理程序,但没有可靠的方法来恢复以前活动的键盘处理程序 - 请参阅GitHub问题#880。
# Set up a key handler that cancels the prompt on pressing ESC (as Ctrl-C would).
Set-PSReadLineKeyHandler -Key Escape -Function CancelLine
try {
# Prompt the user:
Write-Host -NoNewline 'Enter account name you wish to disable: '
$_Name = PSConsoleHostReadLine
# If ESC was pressed, $_Name will contain the empty string.
# Note that you won't be able to distinguish that from the user
# just pressing ENTER.
$canceled = $_Name -eq ''
# ... act on potential cancellation
} finally {
# Remove the custom Escape key handler.
Remove-PSReadlineKeyHandler -Key Escape
}
如果您已将 NirCmd.exe 添加到 Windows 文件夹中,则此简单的读取主机替代功能将在按 Escape 键或您选择的键时退出提示。 (可能也可以使用本机 WScriptShell.SendKeys 方法。)
此函数还将区分空输入(Enter 按键)和 Escape 按键,后者将返回 $null。
function Read-HostX
{
param ([string]$Prompt)
if ($Prompt) { $Prompt = $Prompt + ": " }
Write-Host $Prompt -NoNewline
$key = [Console]::ReadKey($true)
if ($key.Key -eq 'Escape') { return }
elseif ($key.Key -eq 'Enter') { return "" }
else
{
if ($key.Modifiers) { $keyPress = ($key.Modifiers -split ', '), $key.Key -join "+" }
else { $keyPress = $key.Key }
NirCmd.exe sendkeypress $keyPress
return Read-Host
}
}