ok, please do no laugh at this :x
i\'m trying to create a simple software testing tool in VB.NET
i created a simple C program PROG.EXE which scans a number and p
Below is a fully working example. You want to use the Process class as you tried but you need to RedirectStandardOutput on the process's StartInfo. Then you can just read the process's StandardOutput. The sample below is written using VB 2010 but works pretty much the same for older versions.
Option Explicit On
Option Strict On
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
''//This will hold the entire output of the command that we are running
Dim T As String
''//Create our process object
Using P As New Process()
''//Pass it the EXE that we want to execute
''//NOTE: you might have to use an absolute path here
P.StartInfo.FileName = "ping.exe"
''//Pass it any arguments needed
''//NOTE: if you pass a file name as an argument you might have to use an absolute path
P.StartInfo.Arguments = "127.0.0.1"
''//Tell the process that we want to handle the commands output stream
''//NOTE: Some programs also write to StandardError so you might want to watch that, too
P.StartInfo.RedirectStandardOutput = True
''//This is needed for the previous line to work
P.StartInfo.UseShellExecute = False
''//Start the process
P.Start()
''//Wrap a StreamReader around the standard output
Using SR = P.StandardOutput
''//Read everything from the stream
T = SR.ReadToEnd()
End Using
End Using
''//At this point T will hold whatever the process with the given arguments kicked out
''//Here we are just dumping it to the screen
MessageBox.Show(T)
End Sub
End Class
EDIT
Here is an updated version that reads from both StandardOutput
and StandardError
. This time it reads asynchronously. The code calls the CHOICE
exe and passes an invalid command line switch which will trigger writing to StandardError
instead of StandardOutput
. For your program you should probably monitor both. Also, if you're passing a file into the program make sure that you are specifying the absolute path to the file and make sure that if you have spaces in the file path that you are wrapping the path in quotes.
Option Explicit On
Option Strict On
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
''//This will hold the entire output of the command that we are running
Dim T As String
''//Create our process object
Using P As New Process()
''//Pass it the EXE that we want to execute
''//NOTE: you might have to use an absolute path here
P.StartInfo.FileName = "choice"
''//Pass it any arguments needed
''//NOTE: if you pass a file name as an argument you might have to use an absolute path
''//NOTE: I am passing an invalid parameter to show off standard error
P.StartInfo.Arguments = "/G"
''//Tell the process that we want to handle the command output AND error streams
P.StartInfo.RedirectStandardOutput = True
P.StartInfo.RedirectStandardError = True
''//This is needed for the previous line to work
P.StartInfo.UseShellExecute = False
''//Add handlers for both of the data received events
AddHandler P.ErrorDataReceived, AddressOf ErrorDataReceived
AddHandler P.OutputDataReceived, AddressOf OutputDataReceived
''//Start the process
P.Start()
''//Start reading from both error and output
P.BeginErrorReadLine()
P.BeginOutputReadLine()
''//Signal that we want to pause until the program is done running
P.WaitForExit()
Me.Close()
End Using
End Sub
Private Sub ErrorDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
Trace.WriteLine(String.Format("From Error : {0}", e.Data))
End Sub
Private Sub OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
Trace.WriteLine(String.Format("From Output : {0}", e.Data))
End Sub
End Class
Its important that you put your entire file path in quotes if it has spaces in it (in fact, you should always enclose it in quotes just in case.) For instance, this won't work:
P.StartInfo.FileName = "attrib"
P.StartInfo.Arguments = "C:\Program Files\Windows NT\Accessories\wordpad.exe"
But this will:
P.StartInfo.FileName = "attrib"
P.StartInfo.Arguments = """C:\Program Files\Windows NT\Accessories\wordpad.exe"""
EDIT 2
Okay, I'm an idiot. I thought you were just wrapping a filename in angled brackets like <input.txt>
or [input.txt]
, I didn't realize that you were using actual stream redirectors! (A space before and after input.txt
would have helped.) Sorry for the confusion.
There are two ways to handle stream redirection with the Process
object. The first is to manually read input.txt
and write it to StandardInput
and then read StandardOutput
and write that to output.txt
but you don't want to do that. The second way is to use the Windows command interpreter, cmd.exe
which has a special argument /C
. When passed it executes any string after it for you. All stream redirections work as if you typed them at the command line. Its important that whatever command you pass gets wrapped in quotes so along with the file paths you'll see some double-quoting. So here's a version that does all that:
Option Explicit On
Option Strict On
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
''//Full path to our various files
Dim FullExePath As String = "C:\PROG.exe"
Dim FullInputPath As String = "C:\input.txt"
Dim FullOutputPath As String = "C:\output.txt"
''//This creates our command using quote-escaped paths, all completely wrapped in an extra set of quotes
''//""C:\PROG.exe" < "C:\input.txt" > "C:\output.txt""
Dim FullCommand = String.Format("""""{0}"" < ""{1}"" > ""{2}""""", FullExePath, FullInputPath, FullOutputPath)
''//Create our process object
Using P As New Process()
''//We are going to use the command shell and tell it to process our command for us
P.StartInfo.FileName = "cmd"
''//The /C (capitalized) means "execute whatever else is passed"
P.StartInfo.Arguments = "/C " & FullCommand
''//Start the process
P.Start()
''//Signal to wait until the process is done running
P.WaitForExit()
End Using
Me.Close()
End Sub
End Class
EDIT 3
The entire command argument that you pass to cmd /C
needs to be wrapped in a set of quotes. So if you concat it it would be:
Dim FullCommand as String = """""" & FullExePath & """" & " <""" & FullInputPath & """> " & """" & FullOutputPath & """"""
Here's what the actual command that you pass should look like:
cmd /C ""C:\PROG.exe" < "C:\INPUT.txt" > "C:\output.txt""
Here's a full code block. I've added back the error and output readers just in case you're getting a permission error or something. So look at the Immediate Window to see if any errors are kicked out. If this doesn't work I don't know what to tell you.
Option Explicit On
Option Strict On
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
''//Full path to our various files
Dim FullExePath As String = "C:\PROG.exe"
Dim FullInputPath As String = "C:\INPUT.txt"
Dim FullOutputPath As String = "C:\output.txt"
''//This creates our command using quote-escaped paths, all completely wrapped in an extra set of quotes
Dim FullCommand As String = """""" & FullExePath & """" & " <""" & FullInputPath & """> " & """" & FullOutputPath & """"""
Trace.WriteLine("cmd /C " & FullCommand)
''//Create our process object
Using P As New Process()
''//We are going to use the command shell and tell it to process our command for us
P.StartInfo.FileName = "cmd"
''//Tell the process that we want to handle the command output AND error streams
P.StartInfo.RedirectStandardError = True
P.StartInfo.RedirectStandardOutput = True
''//This is needed for the previous line to work
P.StartInfo.UseShellExecute = False
''//Add handlers for both of the data received events
AddHandler P.ErrorDataReceived, AddressOf ErrorDataReceived
AddHandler P.OutputDataReceived, AddressOf OutputDataReceived
''//The /C (capitalized) means "execute whatever else is passed"
P.StartInfo.Arguments = "/C " & FullCommand
''//Start the process
P.Start()
''//Start reading from both error and output
P.BeginErrorReadLine()
P.BeginOutputReadLine()
''//Signal to wait until the process is done running
P.WaitForExit()
End Using
Me.Close()
End Sub
Private Sub ErrorDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
Trace.WriteLine(String.Format("From Error : {0}", e.Data))
End Sub
Private Sub OutputDataReceived(ByVal sender As Object, ByVal e As DataReceivedEventArgs)
Trace.WriteLine(String.Format("From Output : {0}", e.Data))
End Sub
End Class
Public Class attributeclass
Public index(7) As ctrarray
End Class
Public Class ctrarray
Public nameclass As String
Public ctrlindex(10) As ctrlindexclass
End Class
Public Class ctrlindexclass
Public number As Integer
Public names(10) As String
Public status(10) As Boolean
Sub New()
number = 0
For i As Integer = 0 To 10
names(i) = "N/A"
status(i) = False
Next
End Sub
End Class
Public attr As New attributeclass
Sub Main()
attr.index(1).nameclass = "adfdsfds"
System.Console.Write(attr.index(1).nameclass)
System.Console.Read()
End Sub