子プロセスの標準ストリームとして取得できるオブジェクトはStreamWriter/StreamReaderであるため、バイナリ形式での読み書きには向いていません。 また、非同期読み込みでのイベント引数DataReceivedEventArgsも文字列型(≒テキスト形式)として受信されるようになっています。
子プロセスの標準ストリームに対してバイナリ形式の読み書きを行う場合は、まず標準ストリームのStreamWriter/StreamReaderからBaseStreamプロパティを参照することにより、標準ストリームのStreamを取得します。
次に、BaseStreamプロパティから取得したStreamに対して直接読み書きを行うか、StreamからBinaryWriter/BinaryReaderなどを作成して読み書きすることにより、標準ストリームでバイナリ形式のデータを扱うことができるようになります。
Imports System
Imports System.Diagnostics
Imports System.IO
Imports System.Text
Class Sample
Shared Sub Main()
' 子プロセスchild.exeの起動オプション
Dim psi As New ProcessStartInfo("child.exe")
' シェルを使用せず子プロセスを起動する
' (リダイレクトするために必要)
' ⚠.NET Core/.NET 5以降ではデフォルトでFalseとなっている
psi.UseShellExecute = False
' 起動した子プロセスの標準入出力をリダイレクトする
psi.RedirectStandardInput = True
psi.RedirectStandardOutput = True
' 子プロセスを起動する
Using child As Process = Process.Start(psi)
' リダイレクトされた子プロセスの標準入出力を取得する
Dim stdin As StreamWriter = child.StandardInput
Dim stdout As StreamReader = child.StandardOutput
' BaseStreamを参照して標準入出力のStreamを取得し、
' BinaryWriter/BinaryReaderを作成する
Using stdinWriter As New BinaryWriter(stdin.BaseStream)
' 6バイトのバイナリデータを標準入力へ書き込む
stdinWriter.Write(New Byte() {&H48, &H65, &H6C, &H6C, &H6F, &H21})
End Using ' 子プロセスの標準入力を閉じて書き込みを終了する
Dim output As Byte()
Using stdoutReader As New BinaryReader(stdout.BaseStream)
' 標準出力から最大16バイトのバイナリデータを読み込む
output = stdoutReader.ReadBytes(16)
End Using
' 子プロセスの終了を待機する
child.WaitForExit()
' 読み込んだバイナリデータ文字列に変換して表示する
Console.WriteLine(Encoding.ASCII.GetString(output))
End Using
End Sub
End Class
Imports System
Imports System.IO
Imports System.Security.Cryptography
Class Sample
Shared Sub Main()
' 標準入力のStreamを取得
Dim input As Stream = Console.OpenStandardInput()
' 標準出力のStreamをベースに、書き込まれる内容を
' BASE64エンコードするCryptoStreamを作成する
Using output As New CryptoStream(
Console.OpenStandardOutput(),
New ToBase64Transform(),
CryptoStreamMode.Write,
leaveOpen := True
)
' 入力ストリームの内容を出力ストリームに書き込む
' (BASE64エンコードされた上で書き込まれる)
input.CopyTo(output)
End Using
End Sub
End Class
>parent.exe
SGVsbG8h
StandardInput/StandardOutput/StandardErrorで取得できるStreamWriter/StreamReaderは内部でバッファリングが行われます。 このため、StandardInput/StandardOutput/StandardErrorを使った読み書きと、BaseStreamから取得したStreamへの読み書きを混在させると入出力内容に不整合が起こる(入出力されるデータの一部の順序が前後する)可能性があり、両者の使用は排他的とする必要があります。
つまり、BaseStreamから取得したStreamで読み書きを行う場合は、それのみを使って読み書きを行う、あるいはどちらか一方をFlushするまではもう一方を使って読み書きしないようにします。
Windows上では、BaseStreamプロパティから取得したStreamを閉じたあとにStandardOutput/StandardErrorを閉じると、StreamWriterがFlushしようとして例外ObjectDisposedExceptionがスローされます。 そのため、StreamWriterとBaseStreamプロパティから取得したStreamの両方をCloseしないように(二重にCloseする動作とならないように)注意する必要があります。
自プロセスの標準ストリームのStreamを取得する方法については自プロセスの標準入出力 §.標準ストリームの取得を参照してください。
Streamクラスを使った読み書きの方法についてはストリームの基本とStreamクラス、BinaryWriterクラス/BinaryReaderクラスを使った読み書きの方法についてはBinaryReaderクラス・BinaryWriterクラスを参照してください。