BOOL WINAPI ReadFile(
__in HANDLE hFile,
__out LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__out_opt LPDWORD lpNumberOfBytesRead,
__inout_opt LPOVERLAPPED lpOverlapped
);BOOL WINAPI PeekNamedPipe(
__in HANDLE hNamedPipe,
__out_opt LPVOID lpBuffer,
__in DWORD nBufferSize,
__out_opt LPDWORD lpBytesRead,
__out_opt LPDWORD lpTotalBytesAvail,
__out_opt LPDWORD lpBytesLeftThisMessage
); //Takes in a device path and opens a handle to the device.
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);//Uses a handle (created with CreateFile()), and lets us read USB data from the device.
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool ReadFile(
SafeFileHandle hFile,
IntPtr lpBuffer,
uint nNumberOfBytesToRead,
ref uint lpNumberOfBytesRead,
IntPtr lpOverlapped); //Copies data from a named or anonymous pipe into a buffer without removing it from the pipe. It also returns information about data in the pipe.
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool PeekNamedPipe(
SafeFileHandle hFile,
IntPtr lpBuffer,
uint nBufferSize,
ref uint lpBytesRead,
ref uint lpTotalBytesAvail,
ref uint lpBytesLeftThisMessage
);SafeFileHandle ReadHandleToUSBDevice = null;
ReadHandleToUSBDevice = CreateFile(DevicePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
在一个后台进程内调用ReadFile读取USB管道数据会因为没有可供读取的数据而发生阻塞。我尝试先调用PeekNamedPipe以检测是否有数据可供读取,可能是因为方法声明是数据类型定义错误,ErrorStatus = (uint)Marsha.l.GetLastWin32Error();总是返回1或者1008。请问:是否可以使用PeekNamedPipe检测读取缓冲区大小,或者需要采用其他方法?
请问使用SafeFileHandle 可以吗?我现在用SafeFileHandle 形式的声明总是返回0,GetLastError为1。 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool PeekNamedPipe(
SafeFileHandle handle,
byte[] buffer,
uint nBufferSize,
ref uint bytesRead,
ref uint bytesAvail,
ref uint BytesLeftThisMessage);
我尝试使用@"E:\p.txt"作为路径效果一样,可见不是管道的问题???
恕我愚钝,
我确实没有注意到这段话。
即使现在终于看到也还是不能理解。我理解的是如果句柄是同步模式的,且有多个线程使用该句柄,PeekNamedPipe 将阻塞除非其他方法已返回。我调试的时候,读取的句柄是PeekNamedPipe 独享的(有一个写入句柄,已经实践证明不打开写入句柄效果一样),在我的测试环境中,PeekNamedPipe 立即返回了0,并SetLastError = 1。
public unsafe bool ReadFileManagedBuffer(SafeFileHandle hFile, byte[] buffer, uint nNumberOfBytesToRead, ref uint lpNumberOfBytesRead, IntPtr lpOverlapped)
{
IntPtr pINBuffer = IntPtr.Zero; try
{
pINBuffer = Marshal.AllocHGlobal((int)nNumberOfBytesToRead); //Allocate some unmanged RAM for the receive data buffer.
/*
uint bytesRead = 0;
uint bytesAvail = 0;
uint BytesLeftThisMessage = 0;
if (PeekNamedPipe(hFile, pINBuffer, 1, ref bytesRead, ref bytesAvail, ref BytesLeftThisMessage))
{ }
else
{
int err = Marshal.GetLastWin32Error();
if (err != 0)
{
MessageBox.Show(err.ToString());
}
}
*/
if (ReadFile(hFile, pINBuffer, nNumberOfBytesToRead, ref lpNumberOfBytesRead, lpOverlapped))
{
Marshal.Copy(pINBuffer, buffer, 0, (int)lpNumberOfBytesRead); //Copy over the data from unmanged memory into the managed byte[] INBuffer
Marshal.FreeHGlobal(pINBuffer);
return true;
}
else
{
Marshal.FreeHGlobal(pINBuffer);
return false;
} }
catch
{
if (pINBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(pINBuffer);
}
return false;
}
}
ERROR_NO_TOKEN。确定设置了 read?share不设为0应该也有影响LZ问题的最后是怎么回事的?不过没看代码