如何在VB .Net中使用带有WriteFile API的重叠结构

时间:2017-07-15 16:27:36

标签: vb.net api writefile overlapped-io

我使用VB .Net来调用Kernel32.dll WriteFile API:

Public Declare Function WriteFile Lib "kernel32" _ ( _ ByVal hFile As IntPtr, _ ByVal lpBuffer As Byte(), _ ByVal nNumberOfBytesToWrite As Int32, _ ByRef lpNumberOfBytesWritten As Int32, _ ByVal lpOverlapped As IntPtr _ ) _ As Boolean

有人能告诉我如何为这个函数创建一个重叠结构(lpOverlapped),以及如何正确传递它(API需要一个指针吗?)请尽可能显示一个有效的代码片段...

我发现的所有信息要么没有显示可用的示例,要么对我来说太复杂,或者只是不适合VB .Net ...

2 个答案:

答案 0 :(得分:0)

您不需要将指针传递给重叠结构,如果您发现示例太复杂,请不要使用它。 WinAPI通常很复杂,通常更容易在.Net中直接完成所需的操作,并避免使用WinAPI altogehter。

要回答您的问题,结构将被定义为:

Public Structure OVERLAPPED
    Public Internal As Long
    Public InternalHigh As Long
    Public offset As Long
    Public OffsetHigh As Long
    Public hEvent As Long
End Structure

但是,System.Threading有两个类OverlappedNativeOverlapped,旨在让生活更轻松。 Overlapped是一个.Net类,您可以pack加入NativeOverlapped。该结构允许您将回调设置为触发:

在C#中你会这样定义:

Overlapped overlapped = new Overlapped();
NativeOverlapped* nativeOverlapped = overlapped.Pack(
DeviceWriteControlIOCompletionCallback,
null);    

注意我在C#中说过,那是因为VB中的Net. doesn't support the return type,因为它是不安全的代码:

  

Visual Basic不支持使用或返回不安全类型的API。

因此,如果您真的想要重写IO,那么在C#类库中编码重叠方法可能要容易得多,然后您可以在VB应用程序中引用并调用它。

来自All API

  

·lpOverlapped指向OVERLAPPED结构。这种结构是   如果使用FILE_FLAG_OVERLAPPED打开hFile,则必需。如果hFile是   使用FILE_FLAG_OVERLAPPED打开,lpOverlapped参数不能   是NULL。它必须指向有效的OVERLAPPED结构。如果hFile是   用FILE_FLAG_OVERLAPPED打开并且lpOverlapped为NULL,即   函数可能错误地报告写操作已完成。   如果使用FILE_FLAG_OVERLAPPED打开hFile而不是lpOverlapped   NULL,写操作从指定的偏移量开始   OVERLAPPED结构和WriteFile可能在写入之前返回   操作已经完成。在这种情况下,WriteFile返回FALSE   并且GetLastError函数返回ERROR_IO_PENDING。这允许   调用进程在写操作时继续处理   正在完成。 OVERLAPPED结构中指定的事件是   写操作完成后设置为信号状态。如果   没有使用FILE_FLAG_OVERLAPPED打开hFile并且lpOverlapped是   NULL,写操作从当前文件位置开始   在操作完成之前,WriteFile不会返回。如果   hFile没有用FILE_FLAG_OVERLAPPED打开而lpOverlapped没有打开   NULL,写操作从指定的偏移量开始   OVERLAPPED结构和WriteFile在写入之前不会返回   操作已经完成。

答案 1 :(得分:0)

可能已经解决了...我猜它是这样做的:

Dim structPtr As IntPtr
'Create an empty pointer
structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(my_struct))
'Copy the structure and data to the pointer in memory
Marshal.StructureToPtr(my_struct, structPtr, True)