VB.NET 2008 或更高版本:内存违规通过 winapi 读取 STDIN
VB.NET 2008 or higher: Memory violation reading STDIN via winapi
我正在尝试将 VB6 应用程序移植到 VB.NET。
这是一个控制台应用程序,它从STDIN读取数据,修改数据并将其写入STDOUT。
Google 是我的朋友,所以我现在花了几天时间寻找解决方案。
此搜索为我提供了多个版本的 WinApi ReadFile,我尝试了所有版本。
我也尝试了几个版本的 .NET。
但是.....在我尝试过的每一种组合中,我都会不断收到内存冲突错误。
错误因我使用的 ReadFile 变体而略有不同,但都是相似的。
例如,参见错误的这种变体:
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
我用这个来获取句柄:
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
这是产生上述错误的 ReadFile API 调用的变体:
<DllImport("kernel32")>
Declare Function ReadFile(
ByVal hFile As Long,
lpBuffer As String,
nNumberOfBytesToRead As Long,
lpNumberOfBytesRead As Long,
lpOverlapped As String
) As String
这是我发现并尝试过的所有其他变体。都给出类似的错误:
' 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
我在代码中使用它的方式在这里:
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
有人可以帮我找到一种工作方式来读取 STDIN 并写入 VB.NET 中的 STDOUT 吗?
我想知道...
.NET Framework 提供 System.Console
class,其中包含 reading/writing 标准 input/output 流的功能。是否有不使用该功能的特殊原因?
我猜你的 GetData
方法可以改写成这样:
Sub GetData()
sFilterData = Console.In.ReadToEnd()
End Sub
但是,“即时”处理输入流数据可能比先将整个输入流读取并存储到字符串中然后再开始处理更有效(尤其是对于内存使用)。
我正在尝试将 VB6 应用程序移植到 VB.NET。 这是一个控制台应用程序,它从STDIN读取数据,修改数据并将其写入STDOUT。
Google 是我的朋友,所以我现在花了几天时间寻找解决方案。 此搜索为我提供了多个版本的 WinApi ReadFile,我尝试了所有版本。 我也尝试了几个版本的 .NET。 但是.....在我尝试过的每一种组合中,我都会不断收到内存冲突错误。 错误因我使用的 ReadFile 变体而略有不同,但都是相似的。
例如,参见错误的这种变体:
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
我用这个来获取句柄:
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
这是产生上述错误的 ReadFile API 调用的变体:
<DllImport("kernel32")>
Declare Function ReadFile(
ByVal hFile As Long,
lpBuffer As String,
nNumberOfBytesToRead As Long,
lpNumberOfBytesRead As Long,
lpOverlapped As String
) As String
这是我发现并尝试过的所有其他变体。都给出类似的错误:
' 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
我在代码中使用它的方式在这里:
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
有人可以帮我找到一种工作方式来读取 STDIN 并写入 VB.NET 中的 STDOUT 吗?
我想知道...
.NET Framework 提供 System.Console
class,其中包含 reading/writing 标准 input/output 流的功能。是否有不使用该功能的特殊原因?
我猜你的 GetData
方法可以改写成这样:
Sub GetData()
sFilterData = Console.In.ReadToEnd()
End Sub
但是,“即时”处理输入流数据可能比先将整个输入流读取并存储到字符串中然后再开始处理更有效(尤其是对于内存使用)。