开发C# Joy-Con库时FileStream.BeginRead抛出Win32错误1784求助
解决Joy-Con HID通信中Win32错误1784的问题
我之前在做C# HID设备通信项目时刚好踩过这个Win32 1784(缓冲区无效)的坑,结合你开发Joy-Con库的场景,大概率是输入报告缓冲区大小不匹配导致的——这也是HID设备交互里最容易忽略的细节。
核心问题分析
你提到其他项目用49字节的报告长度,但Joy-Con的输入报告长度并不是固定值:它会根据设备当前的工作模式(比如配对模式、常规操作模式)或者你发送的初始化命令发生变化。直接沿用别人的数值,很可能和当前设备实际要求的缓冲区大小不匹配,触发系统的参数校验错误。
具体解决步骤
动态获取Joy-Con的真实输入报告长度
不要硬编码报告长度,通过Windows HID API动态获取才是可靠方案:- 先用
HidD_GetPreparsedData获取设备的预解析数据 - 再调用
HidP_GetCaps获取HIDP_CAPS结构体,其中的InputReportByteLength字段就是设备要求的输入报告字节数
示例代码片段(C# P/Invoke部分):
[DllImport("hid.dll", SetLastError = true)] private static extern bool HidD_GetPreparsedData(IntPtr hidDeviceObject, out IntPtr preparsedData); [DllImport("hid.dll", SetLastError = true)] private static extern HidPStatus HidP_GetCaps(IntPtr preparsedData, out HIDP_CAPS caps); // 定义HIDP_CAPS结构体 [StructLayout(LayoutKind.Sequential)] public struct HIDP_CAPS { public ushort Usage; public ushort UsagePage; public ushort InputReportByteLength; // 其他字段省略... } // 获取报告长度的核心逻辑 if (HidD_GetPreparsedData(deviceHandle, out var preparsedData)) { if (HidP_GetCaps(preparsedData, out var caps) == HidPStatus.Success) { int inputReportLength = caps.InputReportByteLength; // 保存这个长度用于后续缓冲区创建 } HidD_FreePreparsedData(ref preparsedData); // 务必释放资源 }- 先用
保证BeginRead的缓冲区大小完全匹配
用上面获取到的inputReportLength创建读取缓冲区,大小必须和设备要求的完全一致,不能多也不能少:byte[] readBuffer = new byte[inputReportLength]; // 正确调用BeginRead stream.BeginRead(readBuffer, 0, readBuffer.Length, OnReadCompleted, stream);检查FileStream的创建参数
确认创建FileStream时的参数配置合理,建议使用以下设置:FileStream stream = new FileStream(devicePath, FileAccess.ReadWrite, inputReportLength, FileShare.ReadWrite, FileOptions.Asynchronous);这里的第三个参数(缓冲区大小)最好和输入报告长度保持一致,避免额外的内存适配问题。
额外注意事项
- Joy-Con刚连接时可能处于配对模式,此时报告长度和常规操作模式不同,你需要先发送初始化命令(比如设置输入报告模式的指令)切换到工作模式,再获取正确的报告长度。
- 调用HID API后一定要记得释放资源(比如预解析数据、设备句柄),避免内存泄漏。
内容的提问来源于stack exchange,提问作者gjh33
相关产品推荐
相关产品推荐

