user4278054
user4278054

Reputation: 33

PowerShell readline from a stream

Using a PowerShell script I will have to read and write to a console. We write an input and wait for an out that will be captured by $Reader.ReadLine(). But in some cases there wont be any output to get captured for the reader in that case the reader needs to look data from the stream and if there is no data the ReadLine() gets stuck/blocked waiting for the data from the console stream, whereas we need the ReadLine() to just wait for 5 seconds. If there is no data, it needs to get timed out and move on to the next command.

Please let me know whether there is any way to timeout $Reader.ReadLine() in PowerShell?

I see that in Java/C# we can use $Reader.ReadLine(1000) to timeout after 1 second but that doesn't seem to be working on PowerShell.

$tcpConnection = New-Object System.Net.Sockets.TcpClient($Computername, $Port)
$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true

$buffer = New-Object System.Byte[] 1024
$encoding = New-Object System.Text.AsciiEncoding 

while ($tcpStream.DataAvailable) {
    $reader.ReadLine()
}
if ($tcpConnection.Connected) {
    $writer.WriteLine($username)
    $reader.ReadLine()
    $writer.WriteLine($password)
    $reader.ReadLine()

    try {
        # if there is any data it will show here if there is no data then
        # it should get timed out after 5 seconds
        $Reader.ReadLine()
    } catch {
        Write-Host "Login Failed"
    }
}

Upvotes: 3

Views: 6231

Answers (1)

Mötz
Mötz

Reputation: 1732

I would say that you should read this post C# Stream.Read with timeout

Converting that to your code sample, should end up with something like this.

$tcpConnection = New-Object System.Net.Sockets.TcpClient($Computername, $Port)

#This is one way you could try
$tcpConnection.ReceiveTimeout = 5000;

$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)

$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true

$buffer = New-Object System.Byte[] 1024
$encoding = New-Object System.Text.AsciiEncoding 

while ($tcpStream.DataAvailable) {
    $reader.ReadLine()
}
if ($tcpConnection.Connected) {
    $writer.WriteLine($username)
    $reader.ReadLine()
    $writer.WriteLine($password)
    $reader.ReadLine()

    try {
        # if there is any data it will show here if there is no data then
        # it should get timed out after 5 seconds
        $Reader.ReadLine()
    } catch {
        Write-Host "Login Failed"
    }
}

Take it for a spin and let me know if it works or not.

Updated: Updated to reflect the code to only contain the working solution.

Upvotes: 2

Related Questions