I am trying to port a VB6 application to VB.NET. This is a console application that reads data from STDIN, modifies the data and writes it to STDOUT.
Google is my friend, so I have spend days now on finding a solution. This search provided me with several versions of the WinApi ReadFile and I tried them all. Also I have tried several versions of .NET. However.....In every combination that I have tried, I keep getting memory violation errors. Errors differ a little bit depending on the ReadFile variant im using, but the are all similar.
See for instance this variant of the error:
makeDataFilter < Test.in > Test.Out
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at makeDataFilter.Filter_IO.ReadFile(Int64 hFile, String& lpBuffer, Int64 nNumberOfBytesToRead, Int64 lpNumberOfBytesRead, String& lpOverlapped)
at makeDataFilter.Filter_IO.GetData() in C:\Projects\.NET 2019\makeDataFilter\Filter_IO.vb:line 229
at makeDataFilter.Filter_IO.Main() in C:\Projects\.NET 2019\makeDataFilter\Filter_IO.vb:line 118
I use this to get a handle:
Public Const STD_INPUT_HANDLE = -10&
Public Const STD_OUTPUT_HANDLE = -11&
' Open en handle to StdIn or StdOut
Private Declare Function GetStdHandle Lib "kernel32.dll" (
ByVal nStdHandle As Int32
) As IntPtr
Here is the variant of the ReadFile API call that produces the error above:
<DllImport("kernel32")>
Declare Function ReadFile(
ByVal hFile As Long,
lpBuffer As String,
nNumberOfBytesToRead As Long,
lpNumberOfBytesRead As Long,
lpOverlapped As String
) As String
And here are all the other variations that I found and tried. All give similar errors:
' Read from Stdin
'Declare Function ReadFile Lib "kernel32.dll" (
' ByVal hFile As Long,
' lpBuffer As Any,
' ByVal nNumberOfBytesToRead As Long,
' lpNumberOfBytesRead As Long,
' lpOverlapped As Any
') As Long
'Declare Function ReadFile Lib "kernel32" (
' ByVal hFile As Long,
' lpBuffer As String,
' ByVal nNumberOfBytesToRead As Long,
' lpNumberOfBytesRead As Long,
' ByVal lpOverlapped As String
') As Long
'Declare Auto Function ReadFile Lib "Kernel32.dll" (
' ByVal hndRef As Integer,
' ByVal lpBuffer As StringBuilder,
' ByVal numberOfBytesToRead As Integer,
' ByRef numberOfBytesRead As Integer,
' ByVal flag As Integer
') As Boolean
'Declare Function ReadFile Lib "kernel32" (
' ByVal hFile As Integer,
' ByVal lpBuffer As Integer,
' ByVal nNumberOfBytesToRead As Integer,
' lpNumberOfBytesRead As Integer,
' ByVal lpOverlapped As Integer
') As Integer
The way I use it in my code is here:
Sub GetData()
Dim sBuff As String
Dim lBytesRead As Long
Dim rc As Long
lContentLength = 256
sBuff = lContentLength
Do
rc = ReadFile(hStdIn, sBuff, lContentLength, lBytesRead, 0&)
sFilterData &= Left$(sBuff, lBytesRead)
Loop While rc = 1
End Sub
Can somebody please assist me in finding a working way to read from STDIN and write to STDOUT in VB.NET please?
I am wondering...
The .NET Framework provides a System.Console
class, which contains functionality for reading/writing the standard input/output streams. Is there a special reason for not using that functionality?
I guess your GetData
method could be rewritten to something like this:
Sub GetData()
sFilterData = Console.In.ReadToEnd()
End Sub
However, it might be more efficient (especially for memory usage) to process the input stream data "on the fly" instead of reading and storing the entire input stream into a string first and then start processing.