我对 .net/C# 比较陌生(尽管在 Win32 / MFC 和其他平台方面非常有经验),并且需要编写一个实用程序来与自定义 USB HID 设备进行通信。该协议非常简单,我已经有一个用 MFC 编写的工作实用程序,但我更喜欢用 .Net / C# 编写该实用程序,因为我试图与时俱进,将 MFC 抛在后面。
我做了一些调查,发现这篇文章似乎帮助我了解如何从 .Net/C# 访问 HID 设备,特别是因为它只是调用我已经熟悉的 Win32 API 调用:
http://www.developerfusion.com/article/84338/making-usb-c-Friendly/
提供的示例代码很好地介绍了如何访问 Win32 API 调用与 USB 设备通信(就像我以前的 MFC 代码一样),这在 Windows Vista 或 7 的 32 位安装上一切正常,但当我尝试在 64 位安装上运行相同的代码时,它会失败。即使我尝试创建专用的 64 位应用程序,它仍然失败。
我很确定问题在于 Marshal 如何将参数(在堆栈上?)传递给 Win32 API,但我现阶段对 .Net/C# 的知识和经验还不够好,无法准确理解问题是以及如何解决它 - 这个问题可能比我目前所处的水平更高级。
代码中的一切似乎都工作正常,直到我到达指令...
while (SetupDiEnumDeviceInterfaces(hInfoSet, 0, ref gHid, (uint)nIndex, ref oInterface)) // this gets the device interface information for a device at index 'nIndex' in the memory block
其中 SetupDI... 在 32 位系统上返回 true,随后迭代所有连接的 USB 设备,但在 64 位系统上返回 false。我很确定这可能是参数如何传递到 Win32 API 函数的问题,但我不明白确切的问题是什么。该函数的 DLLImport 定义是:
[DllImport("setupapi.dll", SetLastError = true)] protected static extern bool SetupDiEnumDeviceInterfaces(IntPtr lpDeviceInfoSet, uint nDeviceInfoData, ref Guid gClass, uint nIndex, ref DeviceInterfaceData oInterfaceData);
我想知道是否有人能够建议有问题的参数可能是什么以及我如何修复它?
预先感谢您提供的任何帮助,如果需要更多信息,请询问!
富有的
I'm relatively new to .net/C# (though very experienced in Win32 / MFC and other platforms) and need to write a utility to talk to a custom USB HID device. The protocol is pretty simple and I already have a working utility written in MFC, but I would prefer to write the utility in .Net / C# as I'm trying to move with the times and leave MFC behind.
I did some investigation and came across this article which seemed to help me understand how to access HID devices from .Net/C#, especially as it's just calling out the to Win32 API calls I am already familiar with:
http://www.developerfusion.com/article/84338/making-usb-c-friendly/
The sample code provided gave me an excellent introduction to how to access the Win32 API calls to talk to the USB device (just as my previous MFC code did) and this all works fine on a 32 bit installation of Windows Vista or 7, but when I try to run the same code on a 64 bit installation it fails. Even if I try creating a dedicated 64 bit application it still fails.
I'm pretty sure the problem is with how the Marshal is passing the parameters (on the stack?) to the Win32 API, but my knowledge and experience of .Net/C# at this stage is not really good enough to understand exactly what the issue is and how to solve it - the problem is likely more advanced than the level I am currently at.
Everything seems to work fine in the code until I reach the instruction...
while (SetupDiEnumDeviceInterfaces(hInfoSet, 0, ref gHid, (uint)nIndex, ref oInterface)) // this gets the device interface information for a device at index 'nIndex' in the memory block
Where the SetupDI... returns true on 32 bit systems and subsequently iterates through all the connected USB devices but returns false on 64 bit systems. I'm pretty sure it's likely to be an issue with how parameters are being passed into the Win32 API function but I don't understand what the exact problem is. The DLLImport definition for the function is:
[DllImport("setupapi.dll", SetLastError = true)] protected static extern bool SetupDiEnumDeviceInterfaces(IntPtr lpDeviceInfoSet, uint nDeviceInfoData, ref Guid gClass, uint nIndex, ref DeviceInterfaceData oInterfaceData);
I wonder if anyone is able to suggest what the offending parameter might be and how I might fix it?
Thanks in advance for any help offered, if more information is required please ask for it!
Rich
发布评论
评论(2)
来自 MSDN:
请注意,DeviceInfoData 是一个指针 - 所以应该是 IntPtr,而不是 uInt:
并且在调用它时,传递 IntPtr.Zero 而不是 0。
From MSDN:
Note that DeviceInfoData is a pointer - so should be IntPtr, not uInt:
And when calling it, pass IntPtr.Zero instead of 0.
您也许可以通过检查
GetLastError
中的值来追踪有问题的参数问题(如果确实如此),该值可以从Marshal.GetLastWin32Error()
在 .NET 应用程序中。一个可能的问题可能是
oInterface
变量的初始化方式。应该设置 cbSize 元素。该结构 (SP_DEVICE_INTERFACE_DATA) 的 64 位版本可能比 32 位版本更大。刚才简单看了一下,脑子里算了一下(总是容易出错),看起来32位版本是28字节,64位版本是32字节。You might be able to track down the offending parameter problem (if that's what it is) by checking the value from
GetLastError
, which can be obtained fromMarshal.GetLastWin32Error()
in a .NET app.One possible problem might be how the
oInterface
variable is initialized. The cbSize element is supposed to be set. And a 64-bit version of that structure (SP_DEVICE_INTERFACE_DATA) might be larger than the 32-bit version. I looked at it just now briefly and counted in my head (always prone to error), and it looks like the 32-bit version will be 28 bytes, and the 64-bit version would be 32 bytes.