我正在尝试在VB.NET中创建一个简单的软件测试工具
我创建了一个简单的C程序PROG.EXE,它扫描一个数字并打印OUTPUT,并开始构建我的测试器,它应该执行PROG.EXE output.txt,所以PROG.EXE从input.txt获取输入并将输出打印到输出.文本
但我失败了,起初我尝试过Process.start然后shell,但没有任何效果!
所以我做了这个技巧,VB.NET代码使用这个代码生成一个批处理文件PROG.EXE output.txt,但我再次失败,虽然VB.NET创建了批处理文件并执行,但没有任何反应!但是当我手动运行批处理文件时,我获得了成功!
我尝试执行批处理文件然后sendkey VBCR / LF / CRLF仍然没有任何反应!
怎么了 ?
我的VB.NET代码,我使用的是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
这是我的C代码
#include<stdio.h> #include<conio.h> void main() { int x; scanf("%d",&x); printf("%d",(x*x)); }
当我运行prog.exe< input.txt>时,我的程序运行完美.控制台中的output.txt
Process
类,但是您需要在流程的
StartInfo
上使用
RedirectStandardOutput
.然后您可以阅读流程的
StandardOutput
.下面的示例是使用VB 2010编写的,但对于旧版本的工作方式几乎相同.
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
编辑
这是一个从StandardOutput和StandardError读取的更新版本.这次它是异步读取的.代码调用CHOICE exe并传递一个无效的命令行开关,该开关将触发写入StandardError而不是StandardOutput.对于您的程序,您应该监视两者.此外,如果要将文件传递给程序,请确保指定文件的绝对路径,并确保如果文件路径中包含用引号括起路径的空格.
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
重要的是你把整个文件路径放在引号中如果它有空格(事实上,你应该总是将它括在引号中以防万一.)例如,这不起作用:
P.StartInfo.FileName = "attrib" P.StartInfo.Arguments = "C:\Program Files\Windows NT\Accessories\wordpad.exe"
但这会:
P.StartInfo.FileName = "attrib" P.StartInfo.Arguments = """C:\Program Files\Windows NT\Accessories\wordpad.exe"""
编辑2
好吧,我是个白痴.我以为你只是在一个有角度的括号中包装文件名,如< input.txt>或[input.txt],我没有意识到你使用的是实际的流重定向器! (input.txt之前和之后的空格会有所帮助.)很抱歉.
有两种方法可以使用Process对象处理流重定向.第一种是手动读取input.txt并将其写入StandardInput,然后读取StandardOutput并将其写入output.txt,但您不想这样做.第二种方法是使用Windows命令解释器cmd.exe,它具有特殊参数/ C.传递后,它会为你执行任何字符串.所有流重定向都像在命令行中键入它们一样工作.重要的是,无论你传递什么命令都包含在引号中,所以随着文件路径你会看到一些双引号.所以这是一个完成所有这些的版本:
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
编辑3
传递给cmd / C的整个命令参数需要包含在一组引号中.所以如果你连续它会是:
Dim FullCommand as String = """""" & FullExePath & """" & " <""" & FullInputPath & """> " & """" & FullOutputPath & """"""
以下是您传递的实际命令应如下所示:
cmd /C ""C:\PROG.exe" < "C:\INPUT.txt" > "C:\output.txt""
这是一个完整的代码块.我已经添加了错误并输出读者,以防您收到权限错误或其他内容.因此,请查看立即窗口以查看是否有任何错误被踢出.如果这不起作用,我不知道该告诉你什么.
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 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,e.Data)) End Sub End Class