Scripting Network / TCP Connections in PowerShell

Wednesday, 28 October 2009

Awhile back, I introduced a script that allows you interact with remote TCP ports (such as Telnet.) While useful, it worked only interactively. It would be even more useful if you were able to script a network or TCP connection.

################################################################################ Send-TcpRequest.ps1#### From Windows PowerShell Cookbook (O’Reilly)## by Lee Holmes (http://www.leeholmes.com/guide)#### Send a TCP request to a remote computer, and return the response.## If you do not supply input to this script (via either the pipeline, or the## -InputObject parameter,) the script operates in interactive mode.#### Example:#### $http = @"## GET / HTTP/1.1## Host:search.msn.com## `n`n## "@## ## $http | Send-TcpRequest search.msn.com 80##############################################################################param([string]$remoteHost="localhost",[int]$port=80,[switch]$UseSSL,[string]$inputObject,[int]$commandDelay=100)

[string]$output=""

## Store the input into an array that we can scan over. If there was no input,## then we will be in interactive mode.$currentInput=$inputObjectif(-not$currentInput){$SCRIPT:currentInput=@($input)}$scriptedMode=[bool]$currentInput

functionMain{## Open the socket, and connect to the computer on the specified portif(-not$scriptedMode){write-host"Connecting to $remoteHost on port $port"}

while($true){## Receive the output that has buffered so far$SCRIPT:output+=GetOutput

## If we’re in scripted mode, send the commands,## receive the output, and exit.if($scriptedMode){foreach($linein$currentInput){$writer.WriteLine($line)$writer.Flush()Start-Sleep-m$commandDelay$SCRIPT:output+=GetOutput}

break}## If we’re in interactive mode, write the buffered## output, and respond to input.else{if($output){foreach($linein$output.Split("`n")){write-host$line}$SCRIPT:output=""}

## Read the user’s command, quitting if they hit ^D$command=read-hostif($command-eq([char]4)){break;}

## Otherwise, Write their command to the remote host $writer.WriteLine($command)$writer.Flush()}}

## Close the streams$writer.Close()$stream.Close()

## If we’re in scripted mode, return the outputif($scriptedMode){$output}}

## Read output from a remote hostfunctionGetOutput{## Create a buffer to receive the response$buffer=new-objectSystem.Byte[]1024$encoding=new-objectSystem.Text.AsciiEncoding

$outputBuffer=""$foundMore=$false

## Read all the data available from the stream, writing it to the## output buffer when done.do{## Allow data to buffer for a bitstart-sleep-m1000

## Read what data is available$foundmore=$false$stream.ReadTimeout=1000

[Edit: Thanks to Marco for pointing out a few issues that come up when you try to retrieve massive amounts of data (such as a newsgroup listing). I’ve updated the script to fix those.] [Edit2: Updated to call it Send-TcpRequest, and support SSL]

Nice script, do you mind if I take and modify it a bit? I’m interested because with this I should be able to connect to the Manager API of our Asterisk telephony system. By specifying the port 5038 and the IP of my Asterisk server I can connect, which gives me goosebumps for what I can do. This is something I’ve been wanting to try for some time and finally got around to looking at it. Thanks.

Lee, correct me if I’m wrong, but I thought there was an "agreement" that the .ps1 extension indicated the script would run on Powershell V1 and that the .ps2 extension would be used for Powershell V2.

thank you for great script I am using it for scripted telnet communication with ProCurve switches and it runs great. The output is little bit corrupted though, I have tried to change the output AscciEncoding to other format, but no success – Do you have and idea what it might be?

Just a short inquiry about this great script!
I’m having a problem using an input file for my telnet commands.

When I run the script in interactive mode, all works well, but when I put my commands in a text file and use -InputObject “c:\telnet.txt”, this doesn’t seem to work.
I’m probably using -InputObject incorrectly, so I’m hoping you can give sort me out on this one :)

@Arjan , currently you give -InputObject a string “c:\telnet.txt”, powershell doesn’t know the string you give is not the string it needs to process .. you should provide the content of the file.
-InputObject (Get-Content “c:\telnet.txt”)

@Niels, thanks for your reply. It seems that the content of the text file is now read correctly by Telnet. The only problem I have now is that the content of the file consists of several lines of code, which are now read as one long string, instead of seperate lines.
Would you (or anyone else) by any chance know how I can get the command to read one line at a time?
Thanks, Arjan.

Is it possible to use this in conjunction with a ‘listener’ script that will spit out the stuff that I send? It is working well with some printers that we are installing, but I would like to do further testing offline and it seems like the vendor will not be able to provide any help.