pInvoke readFile() : Overlapped I/O operat

2019-06-22 05:44发布

I'm trying to develop a function to communicate with an electronic card. I need to use the readFile() function :

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadFile(IntPtr hFile, ref byte lpBuffer,
       uint nNumberOfBytesToRead, out uint lpNumberOfBytesRead, Overlapped lpOverlapped);

My function is :

EventObject = CreateEvent(IntPtr.Zero,true,true,"");
lastError = Marshal.GetLastWin32Error();

HIDOverlapped = new System.Threading.Overlapped();
HIDOverlapped.OffsetLow = 0;
HIDOverlapped.OffsetHigh = 0;
HIDOverlapped.EventHandleIntPtr = EventObject;

readHandle = CreateFile(MyDeviceInterfaceDetailData.DevicePath, (GENERIC_READ | GENERIC_WRITE), (FILE_SHARE_READ | FILE_SHARE_WRITE), IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, IntPtr.Zero);

 uint numberOfBytesRead;
        readBuffer= new byte[8];
        string byteValue;


 bool result = ReadFile(readHandle, ref readBuffer[0], (uint)capabilities.InputReportByteLength, out numberOfBytesRead, HIDOverlapped);
 lastError = Marshal.GetLastWin32Error(); //Problem

The function Marshal.GetLastWin32Error() in the last line returns error code 997.

In the sencond passage, an other error appears with the code 0xc0000005 (FatalExecutionEngineError) and the software crash.

Have you got an idea of what I can tried?

标签: c# pinvoke
2条回答
疯言疯语
2楼-- · 2019-06-22 05:59

Straight from MSDN:

Because the read operation starts at the offset that is specified in the OVERLAPPED structure, and ReadFile may return before the system-level read operation is complete (read pending), neither the offset nor any other part of the structure should be modified, freed, or reused by the application until the event is signaled (that is, the read completes).

If you read the linked page, you will find that if you pass anything but null as the lpOverlapped parameter it will be an asynchronous call, so most likely your problem comes from the fact, that you try to use the readBuffer before it is set by the function - or in other words: before the read completes.

And as Lucas already indicated in his answer, last error will return 997 while the operation is in progress, so this is the desired output.

查看更多
迷人小祖宗
3楼-- · 2019-06-22 06:07

This is not a problem.

Error code 997 is ERROR_IO_PENDING, which is what ReadFile will return upon starting an overlapped read.

From the docs:

Note The GetLastError code ERROR_IO_PENDING is not a failure; it designates the read operation is pending completion asynchronously. For more information, see Remarks.

Remarks:

ReadFile may return before the read operation is complete. In this scenario, ReadFile returns FALSE and the GetLastError function returns ERROR_IO_PENDING, which allows the calling process to continue while the system completes the read operation.

Is using overlapped I/O a requirement?


How to use overlapped I/O from C# easily?

Using this function definition:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);

You can create regular FileStreams from a file opened with the Win API:

var fileHandle = CreateFile(.....);

if (fileHandle.IsInvalid)
    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());

// The last parameter of the FileStream constructor (isAsync) will make the class use async I/O
using (var stream = new FileStream(fileHandle, FileAccess.ReadWrite, 4096, true))
{
    var buffer = new byte[4096];

    // Asynchronously read 4kb
    var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
}
查看更多
登录 后发表回答