为什么WriteFile使用无效的句柄返回False?

时间:2019-06-03 23:48:03

标签: c# kernel32

我随机遇到返回false的WriteFile(..)方法。当我调用GetLastError()时,返回的值为6。有人知道导致此问题的原因吗?这是我的一些代码:

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer,
    uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
    IntPtr lpOverlapped);

public void Connect()
{
    IntPtr m_WriteHandleToUsbDevice = CreateFile(m_DevicePathName,
        GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING,
        0, IntPtr.Zero).DangerousGetHandle();
}

public void SendCommand()
{
    if (!WriteFile(m_WriteHandleToUsbDevice, command, bytesToWrite, out bytesToWrite, IntPtr.Zero))
    {
        uint lastError = GetLastError(); // lastError = 6
    }
}

我可以成功发送许多命令,但最终在某些时候失败。我已经尝试了WriteFile方法的许多不同签名,但是似乎都没有解决这个问题的方法(大多数只是交换System.Threading.NativeOverlapped结构的最后一个参数)。许多类似的问题是由于NativeOverlapped结构的事件属性未初始化引起的,但是我尝试了失败。以下是我尝试过的替代签名和逻辑之一:

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer,
    uint nNumberOfBytesToWrite, out uint lpNumberOfBytesWritten,
    [In] ref NativeOverlapped lpOverlapped);

public void SendCommand()
{
    var ewh = new EventWaitHandle(false, EventResetMode.AutoReset);
    var unusedOutVariable = new NativeOverlapped {EventHandle = ewh.SafeWaitHandle.DangerousGetHandle()};
    if (!WriteFile(m_WriteHandleToUsbDevice, command, bytesToWrite, out bytesToWrite, IntPtr.Zero))
    {
        uint lastError = GetLastError(); // lastError = 6
    }
}

1 个答案:

答案 0 :(得分:0)

使用DangerousGetHandle()不能使文件保持打开状态。在下一个垃圾收集器传递期间,SafeHandle对象将被检测为不可访问,并将调度其终结器。终结器将关闭手柄。然后,您的其他代码开始失败。 您为什么认为Dangerous一词在函数名称中?

SafeHandle实例保存在类成员数据中,而不要保存在IntPtr中。