为什么 WriteFile Return False 和无效句柄?
Why Does WriteFile Return False With Invalid Handle?
我随机遇到返回 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 方法的许多不同签名,但 none 似乎解决了这个问题(大多数只是将最后一个参数交换为 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
}
}
使用 DangerousGetHandle()
不会使文件保持打开状态。在下一次垃圾收集器传递期间,SafeHandle
对象将被检测为无法访问,并且将安排其终结器。终结器将关闭句柄。然后你的其他代码开始失败。 为什么您认为 Dangerous
这个词出现在函数名称中?
在您的 class 成员数据中保存 SafeHandle
实例而不是 IntPtr
。
我随机遇到返回 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 方法的许多不同签名,但 none 似乎解决了这个问题(大多数只是将最后一个参数交换为 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
}
}
使用 DangerousGetHandle()
不会使文件保持打开状态。在下一次垃圾收集器传递期间,SafeHandle
对象将被检测为无法访问,并且将安排其终结器。终结器将关闭句柄。然后你的其他代码开始失败。 为什么您认为 Dangerous
这个词出现在函数名称中?
在您的 class 成员数据中保存 SafeHandle
实例而不是 IntPtr
。