首页 > 解决方案 > 如何增加 Read-Host 读取的最大字符数?

问题描述

我需要输入一个很长的字符串(大约 9,000 个字符),但Read-Host会在大约 8,000 个字符后截断。我怎样才能延长这个限制?

标签: powershelluser-inputpromptconsole-inputread-host

解决方案


以下是可能的解决方法。解决方法 1 的优点是它可以与需要键盘输入的 PowerShell 后台作业一起使用。请注意,如果您尝试粘贴包含新行的剪贴板内容,Read-HostLine 将仅读取第一行,但 Read-Host 具有相同的行为。

解决方法 1:

<#
.SYNOPSIS
Read a line of input from the host.

.DESCRIPTION
Read a line of input from the host. 

.EXAMPLE
$s = Read-HostLine -prompt "Enter something"

.NOTES
Read-Host has a limitation of 1022 characters.
This approach is safe to use with background jobs that require input.
If pasting content with embedded newlines, only the first line will be read.
A downside to the ReadKey approach is that it is not possible to easily edit the input string before pressing Enter as with Read-Host.
#>
function Read-HostLine ($prompt = $null) {
    if ($prompt) {
        "${prompt}: " | Write-Host
    }

    $str = ""
    while ($true) { 
        $key = $host.UI.RawUI.ReadKey("NoEcho, IncludeKeyDown"); 

        # Paste the clipboard on CTRL-V        
        if (($key.VirtualKeyCode -eq 0x56) -and  # 0x56 is V
            (([int]$key.ControlKeyState -band [System.Management.Automation.Host.ControlKeyStates]::LeftCtrlPressed) -or 
                ([int]$key.ControlKeyState -band [System.Management.Automation.Host.ControlKeyStates]::RightCtrlPressed))) { 
            $clipboard = Get-Clipboard
            $str += $clipboard
            Write-Host $clipboard -NoNewline
            continue
        }
        elseif ($key.VirtualKeyCode -eq 0x08) {  # 0x08 is Backspace
            if ($str.Length -gt 0) {
                $str = $str.Substring(0, $str.Length - 1)
                Write-Host "`b `b" -NoNewline    
            }
        }        
        elseif ($key.VirtualKeyCode -eq 13) {  # 13 is Enter
            Write-Host
            break 
        }
        elseif ($key.Character -ne 0) {
            $str += $key.Character
            Write-Host $key.Character -NoNewline
        }
    }

    return $str
}

解决方法 2:

$maxLength = 65536
[System.Console]::SetIn([System.IO.StreamReader]::new([System.Console]::OpenStandardInput($maxLength), [System.Console]::InputEncoding, $false, $maxLength))

$s = [System.Console]::ReadLine()

解决方法 3:

function Read-Line($maxLength = 65536) {
    $str = ""
    $inputStream = [System.Console]::OpenStandardInput($maxLength);
    $bytes = [byte[]]::new($maxLength);
    while ($true) {
        $len = $inputStream.Read($bytes, 0, $maxLength);
        $str += [string]::new($bytes, 0, $len)
        if ($str.EndsWith("`r`n")) {
            $str = $str.Substring(0, $str.Length - 2)
            return $str
        }
    }
}

$s = Read-Line

更多讨论:
Console.ReadLine() 最大长度?
为什么 Console.Readline() 对它允许的文本长度有限制?
https://github.com/PowerShell/PowerShell/issues/16555


推荐阅读