Ниже приведен полностью рабочий пример.Вы хотите использовать класс Process
, как вы пытались, но вам нужно RedirectStandardOutput
для StartInfo
процесса.Тогда вы можете просто прочитать процесс 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
EDIT 3
Весь аргумент команды, который вы передаете cmd /C
, должен быть заключен в наборцитат.Поэтому, если вы согласитесь, это будет:
Dim FullCommand as String = """""" & FullExePath & """" & " <""" & FullInputPath & """> " & """" & FullOutputPath & """"""
Вот как должна выглядеть действительная команда, которую вы передаете:
cmd /C ""C:\PROG.exe" < "C:\INPUT.txt" > "C:\output.txt""
Вот полный блок кода.Я добавил обратно средства чтения ошибок и вывод на всякий случай, если вы получаете ошибку разрешения или что-то в этом роде.Так что посмотрите на Immediate Window, чтобы увидеть, исключены ли какие-либо ошибки.Если это не сработает, я не знаю, что вам сказать.
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