1

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 prints the OUTPUT, and started building my tester, it should execute PROG.EXE output.txt, so PROG.EXE takes input from input.txt and prints the output to output.txt
but i failed, at first i tried Process.start then shell but nothing worked !
so i did this trick, the VB.NET codes generate a batch file with this codes PROG.EXE output.txt, but again i failed, though the VB.NET created the batch file and executes too, but nothing happened ! but when i manually run the batch file i got success !
i tried executing the batchfile then sendkey the VBCR/LF/CRLF still nothing happens !
whats wrong ?


My VB.NET Code, i am using Visual Studio 2010 Professional

Option Explicit On Option Strict On Public Class Form1 Dim strFileName As String Private Sub btnRun_Click() Handles btnRun.Click Dim strOutput As String Using P As New Process() P.StartInfo.FileName = strFileName P.StartInfo.Arguments = txtInput.Text P.StartInfo.RedirectStandardOutput = True P.StartInfo.UseShellExecute = False P.StartInfo.WindowStyle = ProcessWindowStyle.Hidden ' will this hide the console ? P.Start() Using SR = P.StandardOutput strOutput = SR.ReadToEnd() End Using End Using txtOutput.Text = strOutput End Sub Private Sub btnTarget_Click() Handles btnTarget.Click dlgFile.ShowDialog() strFileName = dlgFile.FileName lblFileName.Text = strFileName End Sub End Class 

And this is my C code

#include<stdio.h> #include<conio.h> void main() { int x; scanf("%d",&x); printf("%d",(x*x)); } 

my program runs perfectly when i run prog.exe <input.txt> output.txt in console

1
  • I'm using Windows XP, Visual Studio 2010 Professional, and the PROG.EXE is written and compiled in Borland Turbo C Commented Apr 18, 2011 at 2:52

2 Answers 2

6
+50

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 
Sign up to request clarification or add additional context in comments.

11 Comments

@Chris Haas Your code worked perfectly for the ping but not for the program i have written in C, so please see my post !
@Chris Haas - thanks for trying again ! but it did not worked for a program which i made with BORLAND TURBO C 2.0 :(
@Sourav, see my EDIT 2 above. I wasn't understanding that you were using stream redirection.
@Chris Haas Your code creates an EMPTY OUTPUT.TXT file when executing from VB.NET ! but if i execute the same command from CMD i get OUTPUT.TXT with results in it ! :(
see my edits too -> Dim FullCommand = """" & FullExePath & """" & " <""" & FullInputPath & """> " & """" & FullOutputPath & """"
|
1
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 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.