【问题标题】:How can I escape a read-host by pressing escape?如何通过按 Escape 来逃脱读取主机?
【发布时间】:2019-04-04 23:46:00
【问题描述】:

只是想知道是否有可能通过按转义键在 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 无法做到这一点。 [grin] 它需要一个“输入”或中断来结束输入,所以如果你必须使用那个 cmdlet,你就会被卡住。如果您想允许这种方式,那么您将需要包装控制台 readkey 方法来读取一个按键一次 - 这不是我的乐趣。 [咧嘴]
  • 啊,好吧,这对脚本来说并不是必需的,只是让它变得更好一点。谢谢你告诉我。
  • 输入一个空白帐户名,并在该行后面有if ("" -eq $_Name) { break }?或者按 Ctrl-C ?
  • @Davkro - 在你的用户提示中添加一个选项,上面写着“选择'x'退出......”...... [grin]

标签: powershell powershell-ise


【解决方案1】:

使用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循环,否则继续执行代码。

【讨论】:

  • 使用 ISE 的 Winforms 或 VisualBasic 时,请注意 this 问题。它并没有阻止我使用 InputBox,但它很烦人。
【解决方案2】:

您无法使用 Read-Host 执行此操作,但您可以通过 PSReadLine module(Windows 10 / Windows Server 2016 上的 Windows PowerShell 版本 5 或更高版本)和 PowerShell Core 及其 PSConsoleHostReadline 函数执行此操作:

重要:

  • 从 PSReadLine v2.0.0-beta3 开始,以下解决方案是 hack,因为 PSConsoleHostReadline 仅支持提示 PowerShell 语句,不是开放式用户输入。

    • GitHub feature suggestion 要求该函数也可选择用于通用用户输入,这将允许高度可定制的最终用户提示体验。如果您希望看到此建议得到实施,请在此处发出您的声音。
  • hack 应该适用于您的案例,因为您提示输入的用户名应该是语法上有效的 PowerShell 语句。

    • 但是,支持任意输入存在问题,原因有两个

      • 将应用不适用的语法着色 - 但是,您可以暂时将所有可配置的颜色设置为相同的颜色,但这会很麻烦。

      • 更重要的是,如果输入恰好是句法上的不完整 PowerShell 语句,PSConsoleHostReadline 将不接受输入,而是继续提示(在新的线);例如,输入a| 会导致此问题。

  • 还有:

    • 无论提交什么输入,都会始终添加到命令历史记录

    • 虽然您目前可以在退出脚本时删除临时安装的键盘处理程序,但没有可靠的方法恢复以前活动的键盘处理程序 - 请参阅 @987654323 @。

 # 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

 }

【讨论】:

    【解决方案3】:

    我写了这个适合我的函数。

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

    【讨论】:

      猜你喜欢
      • 2019-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 2016-02-11
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      相关资源
      最近更新 更多