visual basic .NET get user input without pressing enter - vb.net

I know of the existence of the code character = System.Console.ReadKey().tostring.
This will read one character.
Also in another stack overflow post I found:
Public Shared Function ReadPipedInfo() As StreamReader
'call with a default value of 5 milliseconds
Return ReadPipedInfo(5000)
End Function
Public Shared Function ReadPipedInfo(waitTimeInMilliseconds As Integer) As StreamReader
'allocate the class we're going to callback to
Dim callbackClass As New ReadPipedInfoCallback()
'to indicate read complete or timeout
Dim readCompleteEvent As New AutoResetEvent(False)
'open the StdIn so that we can read against it asynchronously
Dim stdIn As Stream = Console.OpenStandardInput()
'allocate a one-byte buffer, we're going to read off the stream one byte at a time
Dim singleByteBuffer As Byte() = New Byte(0) {}
'allocate a list of an arbitary size to store the read bytes
Dim byteStorage As New List(Of Byte)(4096)
Dim asyncRead As IAsyncResult = Nothing
Dim readLength As Integer = 0
'the bytes we have successfully read
Do
'perform the read and wait until it finishes, unless it's already finished
asyncRead = stdIn.BeginRead(singleByteBuffer, 0, singleByteBuffer.Length, New AsyncCallback(AddressOf callbackClass.ReadCallback), readCompleteEvent)
If Not asyncRead.CompletedSynchronously Then
readCompleteEvent.WaitOne(waitTimeInMilliseconds)
End If
'end the async call, one way or another
'if our read succeeded we store the byte we read
If asyncRead.IsCompleted Then
readLength = stdIn.EndRead(asyncRead)
'If readLength > 0 Then
byteStorage.Add(singleByteBuffer(0))
'End If
End If
Loop While asyncRead.IsCompleted AndAlso readLength > 0
'we keep reading until we fail or read nothing
'return results, if we read zero bytes the buffer will return empty
Return New StreamReader(New MemoryStream(byteStorage.ToArray(), 0, byteStorage.Count))
End Function
Private Class ReadPipedInfoCallback
Public Sub ReadCallback(asyncResult As IAsyncResult)
'pull the user-defined variable and strobe the event, the read finished successfully
Dim readCompleteEvent As AutoResetEvent = TryCast(asyncResult.AsyncState, AutoResetEvent)
readCompleteEvent.[Set]()
End Sub
End Class
which reads input if the user pressed enter
how could I make some code that reads (multiple) character(s) without letting the user press enter all the time? But instead use time as the indicator to stop reading the console?

You can use System.Console.Read() here. It reads as character from standard input stream. https://msdn.microsoft.com/en-us/library/system.console.read(v=vs.110).aspx

According to here I found out how to deal with it:
Public Module ConsoleHelper
Sub Main()
msgbox(ReadKeyWithTimeOut(10000).key.ToString)
End Sub
Public Function ReadKeyWithTimeOut(timeOutMS As Integer) As ConsoleKeyInfo
Dim timeoutvalue As DateTime = DateTime.Now.AddMilliseconds(timeOutMS)
While DateTime.Now < timeoutvalue
If Console.KeyAvailable Then
Dim cki As ConsoleKeyInfo = Console.ReadKey()
Return cki
Else
System.Threading.Thread.Sleep(100)
End If
End While
Return New ConsoleKeyInfo(" "C, ConsoleKey.Spacebar, False, False, False)
End Function
End Module
Now just finding out how to give attribute key NULL or something if it timed out.

Related

How to enlarge a List(of String)(bytes)

I have a variable Queue in which I write information from a stream. The variable is initiated as follows:
Public Shared Queue As List(Of String) = New List(Of String)(1024)
The code to read the stream is
Public Shared Sub ReadStreamForever(ByVal stream As Stream)
Dim encoder = New UTF8Encoding()
Dim buffer = New Byte(2047) {}
Dim counter as Integer = 0
While True
If stream.CanRead Then
Dim len As Integer = stream.Read(buffer, 0, 2048)
Counter = Counter + 1
If len > 0 Then
Dim text = encoder.GetString(buffer, 0, len)
SSEApplication.Push(text)
Else
Exit While
End If
Else
Exit While
End If
End While
End Sub
Where the push methode just does a few string manipulation and adds line after line into the Queue Variable
Public Shared Sub Push(ByVal text As String)
If String.IsNullOrWhiteSpace(text) Then
Return
End If
Dim lines = text.Trim().Split(vbLf)
SSEApplication.Queue.AddRange(lines)
End Sub
I have different big datasets I want to stream but the Queue length after filling it up is always 2691, so it looks like it is kind of limited in length. I just do not know where I limit the Queue Variable and how to enlarge it. Could anyone help me here?
In general, List doesn't have fixed length, Add method resizes List and makes space for another element.
If you want to have fixed length, you could use simple array: Dim Queue(1024) As string
But then, you will get an exception when trying to add more elements, so you can check the condition in Push method:
If lines.Count < 1024 Then
SSEApplication.Queue.AddRange(lines)
End If
That check will also prevent having more than 1024 elements when using List, but if you have collection of fixed length, I would recommend using simple array.
Useful resource: Arrays in Visual Basic, there you can also read, how to enlarge array, when you want to add extra elements using ReDim keyword.

VB.NET Display progress of file decryption?

I'm using this code to encrypt/decrypt files:
Public Shared Sub encryptordecryptfile(ByVal strinputfile As String, _
ByVal stroutputfile As String, _
ByVal bytkey() As Byte, _
ByVal bytiv() As Byte, _
ByVal direction As CryptoAction)
Try
fsInput = New System.IO.FileStream(strinputfile, FileMode.Open, FileAccess.Read)
fsOutput = New System.IO.FileStream(stroutputfile, FileMode.OpenOrCreate, FileAccess.Write)
fsOutput.SetLength(0)
Dim bytbuffer(4096) As Byte
Dim lngbytesprocessed As Long = 0
Dim lngfilelength As Long = fsInput.Length
Dim intbytesincurrentblock As Integer
Dim cscryptostream As CryptoStream
Dim csprijndael As New System.Security.Cryptography.RijndaelManaged
Select Case direction
Case CryptoAction.ActionEncrypt
cscryptostream = New CryptoStream(fsOutput, _
csprijndael.CreateEncryptor(bytkey, bytiv), _
CryptoStreamMode.Write)
Case CryptoAction.ActionDecrypt
cscryptostream = New CryptoStream(fsOutput, _
csprijndael.CreateDecryptor(bytkey, bytiv), _
CryptoStreamMode.Write)
End Select
While lngbytesprocessed < lngfilelength
intbytesincurrentblock = fsInput.Read(bytbuffer, 0, 4096)
cscryptostream.Write(bytbuffer, 0, intbytesincurrentblock)
lngbytesprocessed = lngbytesprocessed + CLng(intbytesincurrentblock)
End While
cscryptostream.Close()
fsInput.Close()
fsOutput.Close()
Catch ex As Exception
End Try
End Sub
Is I need to get the percentage of this process being done as an integer. I am going to use a background worker, so I need to call for this sub from the background worker and be able to keep refreshing a progress bar that the background worker reports to. Is this possible?
Thanks in advance.
There are a couple of things you can do to make your cryptor more efficient and other issues:
A method like encryptordecryptfile which then requires a "mode" argument to know which action to take means it really might be better off as 2 methods
The way you are going, you will be raising a blizzard of ProgressChanged events which the ProgressBar wont be able to keep up with given the animation. A 700K file will result in 170 or so progress reports of tiny amounts
Some of the crypto steps can be incorporated
You have a lot of things not being disposed of; you could run out of resources if you run a number of files thru it in a loop.
It might be worth noting that you can replace the entire While block with fsInput.CopyTo(cscryptostream) to process the file all at once. This doesnt allow progress reporting though. Its also not any faster.
Rather than a BackgroundWorker (which will work fine), you might want to implement it as a Task. The reason for this is that all those variables need to make their way from something like a button click to the DoWork event where your method is actually called. Rather than using global variables or a class to hold them, a Task works a bit more directly (but does involve one extra step when reporting progress). First, a revised EncryptFile method:
Private Sub EncryptFile(inFile As String,
outFile As String,
pass As String,
Optional reporter As ProgressReportDelegate = Nothing)
Const BLOCKSIZE = 4096
Dim percentDone As Integer = 0
Dim totalBytes As Int64 = 0
Dim buffSize As Int32
' Note A
Dim key = GetHashedBytes(pass)
Dim iv = GetRandomBytes(16)
Dim cryptor As ICryptoTransform
' Note B
Using fsIn As New FileStream(inFile, FileMode.Open, FileAccess.Read),
fsOut As New FileStream(outFile, FileMode.OpenOrCreate, FileAccess.Write)
fsOut.SetLength(0)
' Note C
'ToDo: work out optimal block size for Lg vs Sm files
If fsIn.Length > (2 * BLOCKSIZE) Then
' use buffer size to limit to 20 progress reports
buffSize = CInt(fsIn.Length \ 20)
' to multiple of 4096
buffSize = CInt(((buffSize + BLOCKSIZE - 1) / BLOCKSIZE) * BLOCKSIZE)
' optional, limit to some max size like 256k?
'buffSize = Math.Min(buffSize, BLOCK256K)
Else
buffSize = BLOCKSIZE
End If
Dim buffer(buffSize-1) As Byte
' Note D
' write the IV to "naked" fs
fsOut.Write(iv, 0, iv.Length)
Using rij = Rijndael.Create()
rij.Padding = PaddingMode.ISO10126
Try
cryptor = rij.CreateEncryptor(key, iv)
Using cs As New CryptoStream(fsOut, cryptor, CryptoStreamMode.Write)
Dim bytesRead As Int32
Do Until fsIn.Position = fsIn.Length
bytesRead = fsIn.Read(buffer, 0, buffSize)
cs.Write(buffer, 0, bytesRead)
If reporter IsNot Nothing Then
totalBytes += bytesRead
percentDone = CInt(Math.Floor((totalBytes / fsIn.Length) * 100))
reporter(percentDone)
End If
Loop
End Using
Catch crEx As CryptographicException
' ToDo: Set breakpoint and inspect message
Catch ex As Exception
' ToDo: Set breakpoint and inspect message
End Try
End Using
End Using
End Sub
Note A
One of the standard crypto tasks it could handle is creating the Key and IV arrays for you. These are pretty simple and could be shared/static members.
Public Shared Function GetHashedBytes(data As String) As Byte()
Dim hBytes As Byte()
' or SHA512Managed
Using hash As HashAlgorithm = New SHA256Managed()
' convert data to bytes:
Dim dBytes = Encoding.UTF8.GetBytes(data)
' hash the result:
hBytes = hash.ComputeHash(dBytes)
End Using
Return hBytes
End Function
Public Shared Function GetRandomBytes(size As Integer) As Byte()
Dim data(size - 1) As Byte
Using rng As New RNGCryptoServiceProvider
' fill the array
rng.GetBytes(data)
End Using
Return data
End Function
As will be seen later, you can store the IV in the encrypted file rather than saving and managing it in code.
Note B
Using blocks close and dispose of resources for you. Basically, if something has a Dispose method, then you should wrap it in a Using block.
Note C
You dont want to report progress for every block read, that will just overwhelm the ProgressBar. Rather than another variable to keep track of when the progress has changed by some amount, this code starts by creating a buffer size which is 5% of the input file size so there will be about 20 reports (every 5%).
As the comments indicate, you may want to add some code to set minimum/maximum buffer size. Doing so would change the progress report frequency.
Note D
You can write the IV() to the filestream before you wrap it in the CryptoStream (and of course read it back first when Decrypting). This prevents you from having to store the IV.
The last part is kicking this off as a Task:
Dim t As Task
t = Task.Run(Sub() EncryptFile(inFile, oFile, "MyWeakPassword",
AddressOf ReportProgress))
...
What a BGW does is execute the work on one thread, but progress is reported on the UI thread. As a Task, all we need to do is use Invoke:
Delegate Sub ProgressReportDelegate(value As Int32)
Private Sub ReportProgress(v As Int32)
If progBar.InvokeRequired Then
progBar.Invoke(Sub() progBar.Value = v)
Else
progBar.Value = v
progBar.Invalidate()
End If
End Sub
The Encryptor will work either directly or as a Task. For small files, you can omit the progress report entirely:
' small file, no progress report:
EncryptFile(ifile, oFile, "MyWeakPassword")
' report progress, but run on UI thread
EncryptFile(ifile, oFile, "MyWeakPassword",
AddressOf ReportProgress)
' run as task
Dim t As Task
t = Task.Run(Sub() EncryptFile(ifile, oFile, "MyWeakPassword",
AddressOf ReportProgress))
...and if you had a list of files to do, you could run them all at once and perhaps report total progress.

unable to parse value of selected item in a listview object

OK my dilemma is the following, whenever i try to parse a selected item in a listview object it will not pass that value to a function, i know if i use .text or .tostring it will work fine parsing the selected item, but the parsed item will be used as a socket connection, an example of a value selected 127.0.0.1:5688 and for ended the error string cannot be converted to system.net.socket.sockets is trigger when debugging the app if i use listview1.items.item(I).text or tostring
Here is the problematic part
For I As Integer = 0 To ListView1.Items.Count - 1
If ListView1.Items(I).selected = True Then
send(RichTextBox2.Text & vbNewLine, ListView1.Items.Item(I).Tag)
End If
Next
and here is the function where the parsed value is supposed to be passed along
Private Sub Send(ByVal msg As String, ByVal client As Socket)
Dim sendBytes As Byte() = System.Text.ASCIIEncoding.ASCII.GetBytes(msg)
client.BeginSend(sendBytes, 0, sendBytes.Length, SocketFlags.None, New AsyncCallback(AddressOf OnSend), client)
End Sub

store and play microphone data in real time vb.net

as the title says, i'm trying to store and play microphone data in real time with vb.net 2010 and NAudio library. I got this code in C# from the NAudio Codeplex website and i translated it in vb.net.
There's no error in the code and the program works (i put a counter that keeps increasing and updating a label each time mic data is available to see if it's actually working), but i can't hear anything.
here is the code
Imports NAudio
Imports System.IO
'Libraries I'm using
Private Sub wi_dataAvailable(ByVal obj As Object, ByVal e As Wave.WaveInEventArgs) Handles wi.DataAvailable
count += 1 'here is where the counter increases
Label1.Text = count 'and here the label is updated and it seems to work fine
play_packet(e.Buffer)
End Sub
Private Sub play_packet(ByVal DR() As Byte)
Dim MS As New MemoryStream(DR)
Dim frmt As New Wave.WaveFormat
frmt = Wave.WaveFormat.CreateALawFormat(8000, 1)
Dim rsws As New Wave.RawSourceWaveStream(MS, frmt)
Dim pcms As Wave.WaveStream = Wave.WaveFormatConversionStream.CreatePcmStream(rsws)
Dim m_bwp As New Wave.BufferedWaveProvider(New Wave.WaveFormat(8000, 16, 1))
Dim dec() As Byte = cnssb(pcms)
m_bwp.AddSamples(dec, 0, dec.Length)
Dim latency As Integer
Dim cbi As Wave.WaveCallbackInfo = Wave.WaveCallbackInfo.NewWindow
Dim out_dev As New Wave.WaveOut(cbi)
out_dev.DesiredLatency = latency
out_dev.Init(m_bwp)
out_dev.Play()
End Sub
Private Function cnssb(ByVal nss As Wave.WaveStream) As Byte()
Dim memstr As New MemoryStream
Dim buff(1024) As Byte
Dim bytes As Integer
bytes = nss.Read(buff, 0, buff.Length)
While bytes > 0
memstr.Write(buff, 0, bytes)
bytes = nss.Read(buff, 0, buff.Length)
End While
Dim by() As Byte = memstr.ToArray
Return by
End Function
hope you can help me!
You shouldn't be creating a new WaveOut and BufferedWaveProvider every time a recorded buffer is received. Instead create one of each, and just add the audio into the BufferedWaveProvider as you receive it.
Solved!
I declared a boolean variable and then i edited the play_packet function like this:
dim initialized as boolean
'in the form load i set the variable to false
'and then here is the function
Private Sub play_packet(ByVal DR() As Byte)
Dim MS As New MemoryStream(DR)
Dim dec() As Byte = MS.ToArray
m_bwp.AddSamples(dec, 0, dec.Length)
MS.Close()
MS.Dispose()
Dim latency As Integer = 50
Dim cbi As Wave.WaveCallbackInfo = Wave.WaveCallbackInfo.NewWindow
Dim out_dev As New Wave.DirectSoundOut
out_dev.Volume = 1
If initialized = False Then
out_dev.Init(m_bwp)
out_dev.Play()
initialized = True
End If
End Sub

Test telnet communication on remote computer using VB.net?

I have a central server and I need to write a bit of vb.net which will see if I can telnet to a specified server on a specified port.
Is there anyway this can be done in VB.net? I thought about sending command prompts to the remote server to execute telnet, then output the logs of netsh and read those and send the information back to the central server for review.
Its a very messy way of doing it, so I was just wondering if there was an easier way
You should just create a TcpClient object with the IP address of the target server and port (typically 23 for telnet). Then call Connect!
See here for more info:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.aspx
Something like this (may not be exact):
Try
Dim telnetServerIp As String = "192.168.100.55"
Dim telnetPort As Integer = 23
Dim client As New TcpClient(telnetServerIp, telnetPort)
MessageBox.Show("Server is reachable")
Catch ex As Exception
MessageBox.Show("Could not reach server")
End Try
Be advised this is sample code. You'd want to clean up (close/dispose) the connection (TcpClient) object when you were done, etc. But it should get you started.
You should try something to implement this. there are lots help available for Telnet communication using .net.
Take idea from these specified links and implement in vb.net..
How can I open a telnet connection and run a few commands in C#
Telnet connection using .net
You can use a System.Net.Sockets.TcpClient object instead of a
socket object, which already has the socket parameters configured to
use ProtocolType.Tcp
1.Create a new TcpClient object, which takes a server name and a port (no IPEndPoint necessary, nice).
2.Pull a NetworkStream out of the TcpClient by calling GetStream()
3.Convert your message into bytes using Encoding.ASCII.GetBytes(string)
4.Now you can send and receive data using the stream.Write and stream.Read methods, respectively. The stream.Read method returns the number of bytes written to your receiving array, by the way.
5.Put the data back into human-readable format using Encoding.ASCII.GetString(byte array).
6.Clean up your mess before the network admins get mad by calling stream.Close() and client.Close().
Ref:C# 2.0* and Telnet - Not As Painful As It Sounds
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
Int32 port = 13000;
TcpClient client = new TcpClient(server, port);
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
// Stream stream = client.GetStream();
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", message);
I made this for a project at work.
I think it's a complete general solution for most people's needs
However, This is my first real .net project so feel free to critique it.
Modeled on http://www.codeproject.com/Articles/63201/TelnetSocket
Imports System.Threading
Imports System.IO
Imports System.IO.Pipes
Public Class TelnetClient
Private Server As String
Private NetWorkProtocolClient As System.Net.Sockets.TcpClient
Private ServerStream As System.Net.Sockets.NetworkStream
Private DoReader As Boolean
Private ReaderThread As Thread
Private OutputPipe As AnonymousPipeServerStream
Private WaitForString As String
Private WaitForStringEvent As New AutoResetEvent(False)
ReadOnly Property IsConnected() As Boolean
Get
Return (Not (IsNothing(NetWorkProtocolClient)) AndAlso (NetWorkProtocolClient.Connected))
End Get
End Property
ReadOnly Property ConnectedTo() As String
Get
If (Not (IsNothing(NetWorkProtocolClient)) AndAlso (NetWorkProtocolClient.Connected)) Then
Return NetWorkProtocolClient.Client.RemoteEndPoint.ToString()
Else
Return "Nothing"
End If
End Get
End Property
'Set the Server string to connect to.
Public Sub SetServer(ByVal new_server As String)
'double check this later
Server = new_server
End Sub
'Connects if possilbe. If already conneced to some thing it Disconnects from old Telnet and connects to new Telnet.
Public Sub Connect()
Try
If (Not (IsNothing(NetWorkProtocolClient))) AndAlso NetWorkProtocolClient.Connected Then
Disconnect()
End If
If Not IsNothing(Server) Then
NetWorkProtocolClient = New System.Net.Sockets.TcpClient(Server, 23)
If NetWorkProtocolClient.Connected Then
'clear on a new client
WaitForString = Nothing
WaitForStringEvent.Reset()
NetWorkProtocolClient.NoDelay = True
ServerStream = NetWorkProtocolClient.GetStream()
ServerStream.ReadTimeout = 1000
DoReader = True
ReaderThread = New Thread(AddressOf ReaderTask)
ReaderThread.IsBackground = True
ReaderThread.Priority = ThreadPriority.AboveNormal
ReaderThread.Start()
End If
End If
Catch ex As System.Net.Sockets.SocketException
Console.WriteLine("SocketException Connect: {0}", ex)
End Try
End Sub
'Disconnects if connected, otherwise does nothing.
Public Sub Disconnect()
Try
If ReaderThread.IsAlive Then
DoReader = False
ReaderThread.Join(1000)
End If
If (Not (IsNothing(NetWorkProtocolClient))) Then
ServerStream.Close()
NetWorkProtocolClient.Close()
End If
Catch ex As System.Net.Sockets.SocketException
Console.WriteLine("SocketException Disconnect: {0}", ex)
End Try
End Sub
'Returns true if found before timeout milliseconds. Use -1 to have infinite wait time.
'Returns false if timeout occured.
Public Function WaitFor(ByVal command As String, ByVal timeout As Integer) As Boolean
WaitForString = New String(command)
WaitForStringEvent.Reset()
Dim was_signaled As Boolean = False
'Block until a the right value from reader or user defined timeout
was_signaled = WaitForStringEvent.WaitOne(timeout)
WaitForString = Nothing
Return was_signaled
End Function
Public Sub Write(ByVal command As String)
Try
If (Not (IsNothing(NetWorkProtocolClient))) Then
If NetWorkProtocolClient.Connected Then
'Write the value to the Stream
Dim bytes() As Byte = System.Text.Encoding.ASCII.GetBytes(command)
SyncLock ServerStream
ServerStream.Write(bytes, 0, bytes.Length)
End SyncLock
End If
End If
Catch ex As System.Net.Sockets.SocketException
Console.WriteLine("SocketException Write: {0}", ex)
End Try
End Sub
'appends CrLf for the caller
Public Sub WriteLine(ByVal command As String)
Try
If (Not (IsNothing(NetWorkProtocolClient))) Then
If NetWorkProtocolClient.Connected Then
'Write the value to the Stream
Dim bytes() As Byte = System.Text.Encoding.ASCII.GetBytes(command & vbCrLf)
SyncLock ServerStream
ServerStream.Write(bytes, 0, bytes.Length)
End SyncLock
End If
End If
Catch ex As System.Net.Sockets.SocketException
Console.WriteLine("SocketException Write: {0}", ex)
End Try
End Sub
'Get a pipe to read output. Note: anything written by WriteLine may be echoed back if the other Telnet offers to do it.
Public Function GetPipeHandle() As String
If Not IsNothing(ReaderThread) AndAlso ReaderThread.IsAlive AndAlso Not IsNothing(OutputPipe) Then
Return OutputPipe.GetClientHandleAsString
Else
Return Nothing
End If
End Function
'Task that watches the tcp stream, passes info to the negotiation function and signals the WaitFor task.
Private Sub ReaderTask()
Try
OutputPipe = New AnonymousPipeServerStream(PipeDirection.Out)
Dim prevData As New String("")
While (DoReader)
If (Not (IsNothing(NetWorkProtocolClient))) Then
If ServerStream.DataAvailable Then
'Grab Data
Dim data As [Byte]() = New [Byte](NetWorkProtocolClient.ReceiveBufferSize) {}
Dim bytes As Integer = ServerStream.Read(data, 0, data.Length)
'Negotiate anything that came in
bytes = Negotiate(data, bytes)
If (bytes > 0) Then
'append previous to the search sting incase messages were fragmented
Dim s As New String(prevData & System.Text.ASCIIEncoding.ASCII.GetChars(data))
'If Pipe is connected send it remaining real data
If OutputPipe.IsConnected Then
OutputPipe.Write(data, 0, bytes)
End If
'Check remaining against WaitForString
If Not IsNothing(WaitForString) Then
If s.Contains(WaitForString) Then
WaitForStringEvent.Set()
'clear prevData buffer because the WaitForString was found
prevData = New String("")
Else
'Nothing found make the current string part of the next string.
prevData = New String(s)
End If
Else
prevData = New String("")
End If
End If
Else
Thread.Sleep(100)
End If
End If
End While
OutputPipe.Close()
OutputPipe.Dispose()
Catch ex As System.IO.IOException
Console.WriteLine("IO Error: {0}", ex)
Catch ex As System.Net.Sockets.SocketException
Console.WriteLine("SocketException Reader: {0}", ex)
End Try
End Sub
'Shamelessly adapted from http://www.codeproject.com/Articles/63201/TelnetSocket
'The basic algorithm used here is:
' Iterate across the incoming bytes
' Assume that an IAC (byte 255) is the first of a two- or three-byte Telnet command and handle it:
' If two IACs are together, they represent one data byte 255
' Ignore the Go-Ahead command
' Respond WONT to all DOs and DONTs
' Respond DONT to all WONTs
' Respond DO to WILL ECHO and WILL SUPPRESS GO-AHEAD
' Respond DONT to all other WILLs
' Any other bytes are data; ignore nulls, and shift the rest as necessary
' Return the number of bytes that remain after removing the Telnet command and ignoring nulls
Private Function Negotiate(ByVal data As Byte(), ByVal length As Int32) As Int32
Dim index As Int32 = 0
Dim remaining As Int32 = 0
While (index < length)
If (data(index) = TelnetBytes.IAC) Then
Try
Select Case data(index + 1)
Case TelnetBytes.IAC
data(remaining) = data(index)
remaining += 1
index += 2
Case TelnetBytes.GA
index += 2
Case TelnetBytes.WDO
data(index + 1) = TelnetBytes.WONT
SyncLock ServerStream
ServerStream.Write(data, index, 3)
End SyncLock
index += 3
Case TelnetBytes.DONT
data(index + 1) = TelnetBytes.WONT
SyncLock ServerStream
ServerStream.Write(data, index, 3)
End SyncLock
index += 3
Case TelnetBytes.WONT
data(index + 1) = TelnetBytes.DONT
SyncLock ServerStream
ServerStream.Write(data, index, 3)
End SyncLock
index += 3
Case TelnetBytes.WILL
Dim action As Byte = TelnetBytes.DONT
Select Case data(index + 2)
Case TelnetBytes.ECHO
action = TelnetBytes.WDO
Case TelnetBytes.SUPP
action = TelnetBytes.WDO
End Select
data(index + 1) = action
SyncLock ServerStream
ServerStream.Write(data, index, 3)
End SyncLock
index += 3
End Select
Catch ex As System.IndexOutOfRangeException
index = length
End Try
Else
If (data(index) <> 0) Then
data(remaining) = data(index)
remaining += 1
End If
index += 1
End If
End While
Return remaining
End Function
Private Structure TelnetBytes
'Commands
Public Const GA As Byte = 249
Public Const WILL As Byte = 251
Public Const WONT As Byte = 252
Public Const WDO As Byte = 253 'Actually just DO but is protected word in vb.net
Public Const DONT As Byte = 254
Public Const IAC As Byte = 255
'Options
Public Const ECHO As Byte = 1
Public Const SUPP As Byte = 3
End Structure
End Class