xinglong
xinglong

Reputation: 115

How can I increase the maximum number of characters read by Read-Host?

I need to get a very long string input (around 9,000 characters), but Read-Host will truncate after around 8,000 characters. How can I extend this limit?

Upvotes: 0

Views: 1000

Answers (1)

KrisG
KrisG

Reputation: 149

The following are possible workarounds. Workaround 1 has the advantage that it will work with PowerShell background jobs that require keyboard input. Note that if you are trying to paste clipboard content containing new lines, Read-HostLine will only read the first line, but Read-Host has this same behavior.

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

Workaround 2:

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

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

Workaround 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

More discussion here:
Console.ReadLine() max length?
Why does Console.Readline() have a limit on the length of text it allows?
https://github.com/PowerShell/PowerShell/issues/16555

Upvotes: 1

Related Questions