VB.net difficulty in using RedirectStandardInput for my program - vb.net

I am trying to make a simple chat program in vb using netcat. Here is my code
Public Class Form1
Dim p As New Process
Dim pstrt As New System.Diagnostics.ProcessStartInfo
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Go()
End Sub
Sub Go()
pstrt.FileName = "cmd.exe"
pstrt.Arguments = "/c nc -l -p1234"
pstrt.UseShellExecute = False
pstrt.RedirectStandardOutput = True
pstrt.RedirectStandardInput = True
AddHandler p.OutputDataReceived, AddressOf yo
p.StartInfo = pstrt
p.Start()
p.BeginOutputReadLine()
End Sub
Sub yo(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
UpdateTextBox(e.Data)
End Sub
Private Delegate Sub UpdateTextBoxDelegate(ByVal Text As String)
Private Sub UpdateTextBox(ByVal tot As String)
If Me.InvokeRequired Then
Dim delgt As New UpdateTextBoxDelegate(AddressOf UpdateTextBox)
Dim args As Object() = {tot}
Me.Invoke(delgt, args)
Else
RichTextBox1.Text &= tot & Environment.NewLine
End If
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
'Shell(TextBox1.Text)
'Console.WriteLine(TextBox1.Text)
p.StandardInput.WriteLine(TextBox1.Text)
End Sub
End Class
The form has a richtextbox, a textbox and two buttons.
The problem is that:
when using redirectstandardinput, the received text is not displayed in richtextbox but the sent text can be viewed by the receiver.
when I don't redirectstandardinput then the received text is displayed in the richtextbox but the sent text cannot be viewed by the receiver.
I have also tried to use the commented code (for button2 click code) to use to send text when not using redirectstandardinput.

For me, your code is working correctly without changes, with
pstrt.RedirectStandardOutput = True
pstrt.RedirectStandardInput = True
See the screenshot:
I guess your problem can be with netcat.
Try with simple commands first like seen on the sample.
Try on another machine. I tested on Windows 8.0, .NET 4.0.

Related

Running an external app in textbox (how to preserve all functionality?)

I'm trying to run a cmd like application (so no GUI) in my form. In the example down below I called it ExternalApp.exe. The code itself works; I can send commands to it by entering them in TextBox2. The issue is that ExternalApp normally uses a command prompt and supports things like displaying one single screen of output and then wait for an enter before showing the next one. This is no longer working, all output is sent to TextBox1 all at once.
Is there any way to have ExternalApp behave like it normally does? I hope I'm explained myself a bit clear. Thanks for any help in advance!
Kind regards,
Eric
Public Class Form1
Dim WithEvents P As New Process
Dim SW As System.IO.StreamWriter
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
P.EnableRaisingEvents = True
Me.Text = "My title"
AddHandler P.OutputDataReceived, AddressOf DisplayOutput
P.StartInfo.CreateNoWindow() = True
P.StartInfo.UseShellExecute = False
P.StartInfo.RedirectStandardInput = True
P.StartInfo.RedirectStandardOutput = True
P.StartInfo.FileName = "ExternalApp.exe"
P.StartInfo.Arguments = ""
P.Start()
P.SynchronizingObject = Me
P.BeginOutputReadLine()
SW = P.StandardInput
SW.WriteLine()
End Sub
Private Sub DisplayOutput(ByVal sendingProcess As Object, ByVal output As DataReceivedEventArgs)
TextBox1.AppendText(output.Data() & vbCrLf)
End Sub
Private Sub Textbox2_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox2.KeyPress
If e.KeyChar = Chr(Keys.Return) Then
SW.WriteLine(TextBox2.Text)
End If
End Sub
Private Sub myProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles P.Exited
Me.Close()
End Sub End Class

Unload Form1 when embedded cmd process ends

I have found some code which runs a cmd.exe shell interactively in a TextBox; later on I will replace cmd.exe with a different character based application.
Here's the code:
Public Class Form1
Dim P As New Process
Dim SW As System.IO.StreamWriter
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Text = "My title"
AddHandler P.OutputDataReceived, AddressOf DisplayOutput
P.StartInfo.CreateNoWindow() = True
P.StartInfo.UseShellExecute = False
P.StartInfo.RedirectStandardInput = True
P.StartInfo.RedirectStandardOutput = True
P.StartInfo.FileName = "cmd"
P.Start()
P.SynchronizingObject = TextBox1
P.BeginOutputReadLine()
SW = P.StandardInput
SW.WriteLine()
End Sub
Private Sub DisplayOutput(ByVal sendingProcess As Object, ByVal output As DataReceivedEventArgs)
TextBox1.AppendText(output.Data() & vbCrLf)
End Sub
Private Sub Textbox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
Static Line As String
If e.KeyChar = Chr(Keys.Return) Then
SW.WriteLine(Line & vbCrLf)
Line = ""
Else
Line = Line & e.KeyChar
End If
End Sub
End Class
When you enter the exit command, the cmd.exe process terminates.
I like my application to unload Form1 when this occurs, but I don't know how to implement this.
As suggested by Jimi, I added the following line to he Form1_Load sub:
P.EnableRaisingEvents = True
and added:
Private Sub myProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles P.Exited
Me.Close()
End Sub
This is working; thank you very much Jimi!
Add this above End Sub in your Form1_Load Sub:
p.WaitForExit()
Form1.Close()
Since it looks like you're calling it from Form1 itself, you could also use Me.Close.
If Form1 is the only form and you want the whole application to close, you can use Application.Exit() instead.
Some references:
http://www.vb-helper.com/howto_net_start_notepad_wait.html
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.form.close?view=windowsdesktop-6.0

when the text in a textbox is equal to a certain word i need to value in the combo box to be saved for that text

I have orders in text files in the debug folder and when i type the name of the order in a text box it displays the order is a list box and there is a combo box underneath where i can change the status of the meal preparation (Being prepared, ready to deliver etc,). If i go back to that form and type in the same order name into the textbox i need to previous prepartion status to be already in the textbox. Thanks for any help!
Public Class frmOrderStatus
Private Sub btnStatus_Click(sender As Object, e As EventArgs) Handles btnStatus.Click
Dim sr As IO.StreamReader = IO.File.OpenText(strTxtOrderNum & ".txt")
Do Until sr.EndOfStream
lstOrder.Items.Add(sr.ReadLine)
Loop
End Sub
Private Sub OrderStatus_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lstOrder.Items.Clear()
btnStatus.Enabled = False
ChangeStatus.Enabled = False
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnValidate.Click
strTxtOrderNum = txtOrderNum2.Text
btnStatus.Enabled = True
ChangeStatus.Enabled = True
End Sub
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
strSaveStatus = ChangeStatus.SelectedIndex
End Sub
Private Sub ChangeStatus_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ChangeStatus.SelectedIndexChanged
End Sub
End Class
It recognizes the file; it just tells you it is in use. A Stream must be closed and disposed. I don't see the StreamReader even being closed let alone disposed. A `Using...End Using block will close and dispose of objects even if there is an error.
I just used a text file I happened to have to test.
Private strTxtOrderNum As String = "host"
Private Sub ReadFile()
Using sr As IO.StreamReader = IO.File.OpenText(strTxtOrderNum & ".txt")
Do Until sr.EndOfStream
ListBox1.Items.Add(sr.ReadLine)
Loop
End Using
End Sub
Private Sub WriteFile()
Dim strSelectedItem = ComboBox1.Text
Using swVar As IO.StreamWriter = IO.File.AppendText(strTxtOrderNum & ".txt")
swVar.WriteLine(strSelectedItem)
End Using
End Sub

Get Jar output in vb and send commands

really need help! I would like to know how to get jar output into a textbox in VB 2008.
Also i would like to send commands to it (like CMD would when you use this command:
C:\Windows\System32\java.exe -Xms128M -Xmx1024M -jar Craftbukkit.jar)
Below a proof of concept. You'll have to tweak it to your own desires and wishes. What does this do:
Start a process in the background
Start reading the output and error streams.
You can send commands via a textbox (and a click on a button).
Write the output/errors in an output textbox.
Again, this code is just a proof of concept, it is far from finished (but it demonstrates enough). You'll have to add some extra checks etc to make it "waterproof".
Public Class MyForm
Private WithEvents _CmdProcess As Process
Private Delegate Sub DisplayTextDelegate(text As String)
Private Sub MyForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim processInfo As New ProcessStartInfo()
processInfo.FileName = "cmd"
processInfo.RedirectStandardError = True
processInfo.RedirectStandardInput = True
processInfo.RedirectStandardOutput = True
processInfo.UseShellExecute = False
processInfo.CreateNoWindow = True
_CmdProcess = Process.Start(processInfo)
_CmdProcess.BeginOutputReadLine()
_CmdProcess.BeginErrorReadLine()
End Sub
Private Sub MyForm_Disposed(sender As System.Object, e As System.EventArgs) Handles MyBase.Disposed
If _CmdProcess IsNot Nothing Then
_CmdProcess.Close()
End If
_CmdProcess = Nothing
End Sub
Private Sub btnExecute_Click(sender As System.Object, e As System.EventArgs) Handles btnExecute.Click
If Not String.IsNullOrWhiteSpace(txtCommand.Text) Then
Dim inputStream As System.IO.StreamWriter = _CmdProcess.StandardInput
inputStream.WriteLine(txtCommand.Text)
inputStream.Flush()
End If
End Sub
Private Sub CmdProcess_ErrorDataReceived(sender As System.Object, e As System.Diagnostics.DataReceivedEventArgs) Handles _CmdProcess.ErrorDataReceived
Invoke(New DisplayTextDelegate(AddressOf DisplayText), Environment.NewLine)
Invoke(New DisplayTextDelegate(AddressOf DisplayText), "Error!")
Invoke(New DisplayTextDelegate(AddressOf DisplayText), e.Data)
End Sub
Private Sub CmdProcess_OutputDataReceived(sender As System.Object, e As System.Diagnostics.DataReceivedEventArgs) Handles _CmdProcess.OutputDataReceived
Invoke(New DisplayTextDelegate(AddressOf DisplayText), e.Data)
End Sub
Private Sub DisplayText(text As String)
txtOutput.AppendText(Environment.NewLine)
txtOutput.AppendText(text)
End Sub
End Class

how to run a function/sub after loading the form window in VB?

I have a function that gets User ID from USB badge reader, used to log in an application.
when I run the app, the log in window does not appear until I swipe the tag.
I need to know if it`s possible to load the windows, then to start running the function that gets the data from the USB.
Thanks :)
Private Sub SerialPort1_DataReceived()
'Threading.Thread.SpinWait(1000)
OpenPort()
If SerialPort1.IsOpen() Then
byteEnd = SerialPort1.NewLine.ToCharArray
'read entire string until .Newline
readBuffer = SerialPort1.ReadLine()
readBuffer = readBuffer.Remove(0, 1)
readBuffer = readBuffer.Remove(8, 1)
WWIDTextBox.AppendText(readBuffer)
End If
End Sub
Private Sub Form1_Activated(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
SerialPort1_DataReceived()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'SerialPort1_DataReceived()
End Sub
The problem is that you are calling the ReadLine method, which is a blocking (synchronous) method. In other words, when you call it, the method does not return the value until it has the value to return. Because of that, it stops execution on the current thread until a complete line is read (when the badge is swiped). Since you are on the UI thread when you call it, it will lock up the UI until the badge is swiped.
Instead of calling your SerialPort1_DataReceived method from the UI thread, you can do the work from a different thread. The easiest way to do that is to drag a BackgroundWorker component onto your form in the designer. Then you can add code like this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
OpenPort()
If SerialPort1.IsOpen() Then
byteEnd = SerialPort1.NewLine.ToCharArray
Dim readBuffer As String = SerialPort1.ReadLine()
readBuffer = readBuffer.Remove(0, 1)
readBuffer = readBuffer.Remove(8, 1)
e.Result = readBuffer
End If
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
WWIDTextBox.AppendText(CStr(e.Result))
End Sub
Working on VS2013, I came across the same issue, I needed to to a datagridview refresh (colors in the gridrows). This worked for me.
Sub MyForm_VisibleChanged(sender As Object, e As EventArgs) Handles Me.VisibleChanged
If Me.Visible Then
'do action...
End If
End Sub
Try Form Activated Event
Private Sub Form1_Activated(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Activated
'Call your function here
End Sub
It call the function After the Form Loads...
Private Sub loadCombo()
Dim sqlconn As New OleDb.OleDbConnection
Dim connString As String
connString = ""
Dim access As String
access = "select slno from atable"
Dim DataTab As New DataTable
Dim DataAdap As New OleDbDataAdapter(access, connString)
DataAdap.Fill(DataTab)
ComboBox1.DataSource = DataTab
ComboBox1.DisplayMember = "slno"
End Sub