简体   繁体   English

C ++的C#USB驱动程序

[英]C# USB driver from C++

I've a problem trying to call SetupDiEnumDeviceInterfaces from C#. 我在尝试从C#调用SetupDiEnumDeviceInterfaces时遇到问题。 It always returns 1784 error code ("The supplied user buffer is not valid for the requested operation"). 它始终返回1784错误代码(“提供的用户缓冲区对于请求的操作无效”)。 On the same machine if I execute the corrisponding C++ code the function is successful. 在同一台机器上,如果我执行相应的C ++代码,该函数将成功执行。 This is my C# code: 这是我的C#代码:

        Guid classGuid = GUID_DEVINTERFACE_DFU; // Guid(0x3fe809ab, 0xfb91, 0x4cb5, 0xa6, 0x43, 0x69, 0x67, 0x0d, 0x52,0x36,0x6e)

        IntPtr hDevInfo = Win32.SetupDiGetClassDevs(ref classGuid, IntPtr.Zero, IntPtr.Zero, Win32.DIGCF_DEVICEINTERFACE | Win32.DIGCF_PRESENT);
        if (hDevInfo.ToInt32() == Win32.INVALID_HANDLE_VALUE)
        {
            Console.WriteLine("read hardware information error");
        }
        else
        {
            uint i = 0;
            SP_DEVINFO_DATA devInfoData = new SP_DEVINFO_DATA();
            devInfoData.classGuid = Guid.Empty;
            devInfoData.devInst = 0;
            devInfoData.reserved = IntPtr.Zero;

            bool result = Win32.SetupDiEnumDeviceInfo(hDevInfo, i, devInfoData);
            if (false == result)
            {
                int error = Marshal.GetLastWin32Error();
                if (error != Win32.ERROR_NO_MORE_ITEMS)
                    throw new Win32Exception(error);
            }

            SP_DEVICE_INTERFACE_DATA ifData = new SP_DEVICE_INTERFACE_DATA();
            ifData.cbSize = 50;
            ifData.Flags = 0;
            ifData.InterfaceClassGuid = Guid.Empty;
            ifData.Reserved = IntPtr.Zero;

            bool result2 = Win32.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, ref classGuid, i, ref ifData);
            if(result2 == false)
            {
                int error = Marshal.GetLastWin32Error();
                if (error != Win32.ERROR_NO_MORE_ITEMS)
                    throw new Win32Exception(error);
            }
        }


[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINFO_DATA
{
    public uint cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
    public Guid classGuid;
    public uint devInst;
    public IntPtr reserved;
};

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public class SP_DEVICE_INTERFACE_DATA
{
    public uint cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA));
    public Guid InterfaceClassGuid;
    public uint Flags;
    public IntPtr Reserved;
}

public class Win32
{
    [DllImport("setupapi.dll", SetLastError = true)]
    public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, uint Flags);   

    [DllImport("setupapi.dll", SetLastError = true)]
    public static extern Boolean SetupDiEnumDeviceInfo(IntPtr lpInfoSet, UInt32 dwIndex, SP_DEVINFO_DATA devInfoData);

    public const int DIGCF_PRESENT = 0x02;
    public const int DIGCF_DEVICEINTERFACE = 0x10;
    public const long ERROR_NO_MORE_ITEMS = 259L;
}

And this is my C++ code: 这是我的C ++代码:

    GUID Guid=GUID_DFU;  // { 0x3fe809ab, 0xfb91, 0x4cb5, { 0xa6, 0x43, 0x69, 0x67, 0x0d, 0x52,0x36,0x6e } }
    HDEVINFO info = SetupDiGetClassDevs(&Guid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
    if (info!=INVALID_HANDLE_VALUE)  
    {
        SP_INTERFACE_DEVICE_DATA ifData;
        ifData.cbSize=sizeof(ifData);

        bool result = SetupDiEnumDeviceInterfaces(info, NULL, &Guid, devIndex, &ifData);
    }

The code is running on Windows 8.1 x64 and the C# application platform is x86. 该代码在Windows 8.1 x64上运行,C#应用程序平台为x86。

You declare SP_DEVICE_INTERFACE_DATA to be a class in the C# code. 您将SP_DEVICE_INTERFACE_DATA声明为C#代码中的类。 That means that it is already a reference. 这意味着它已经是参考。 You then pass the SP_DEVICE_INTERFACE_DATA instance by reference to SetupDiEnumDeviceInfo . 然后,通过引用SetupDiEnumDeviceInfo传递SP_DEVICE_INTERFACE_DATA实例。 Which means that you are passing SP_DEVICE_INTERFACE_DATA** rather than SP_DEVICE_INTERFACE_DATA* , in C++ terms. 这意味着您使用C ++术语传递了SP_DEVICE_INTERFACE_DATA**而不是SP_DEVICE_INTERFACE_DATA*

Either: 要么:

  1. Change SP_DEVICE_INTERFACE_DATA to be a struct, or SP_DEVICE_INTERFACE_DATA更改为结构,或者
  2. Leave SP_DEVICE_INTERFACE_DATA as a class, but pass it by value. SP_DEVICE_INTERFACE_DATA保留为类,但按值传递它。 That is, as you did with SP_DEVINFO_DATA and SetupDiEnumDeviceInfo . 也就是说,就像使用SP_DEVINFO_DATASetupDiEnumDeviceInfo

You are setting cbSize incorrectly. 您设置的cbSize错误。 It should be: 它应该是:

ifData.cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA));

There's no point in setting the other members of SP_DEVICE_INTERFACE_DATA since they are ignored by the function that you call. 设置SP_DEVICE_INTERFACE_DATA的其他成员没有任何意义,因为您调用的函数将忽略它们。 That function's job is to populate those members. 该职能部门的职责是填充这些成员。

There may be other problems. 可能还有其他问题。 It's hard to say because you have not posted your actual code. 很难说,因为您尚未发布实际代码。 The C++ code does not compile, and the C# code is incomplete. C ++代码无法编译,并且C#代码不完整。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM