首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >64位架构上的SetupDiEnumDeviceInterfaces在C#上

64位架构上的SetupDiEnumDeviceInterfaces在C#上
EN

Stack Overflow用户
提问于 2014-11-10 19:16:19
回答 2查看 4.1K关注 0票数 3

我尝试在64位架构上从SetupDiEnumDeviceInterfaces中调用Window API函数C#。我导入函数并声明其他结构。

代码语言:javascript
复制
    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    internal static extern bool SetupDiEnumDeviceInterfaces(
        IntPtr deviceInfoSet,
        SP_DEVINFO_DATA deviceInfoData,
        ref Guid interfaceClassGuid,
        int memberIndex,
        SP_DEVICE_INTERFACE_DATA deviceInterfaceData);

    [StructLayout(LayoutKind.Sequential)]
    internal class SP_DEVINFO_DATA
    {
        internal int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
        internal Guid classGuid = Guid.Empty; // temp
        internal int devInst = 0; // dumy
        internal int reserved = 0;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 2)]
    internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
    {
        internal int cbSize;
        internal short devicePath;
    }

然后,我按如下方式调用此函数:

代码语言:javascript
复制
        int index = 0;
        Guid _classGuid = Guid.Empty;
        IntPtr _deviceInfoSet = IntPtr.Zero;

        Native.SP_DEVICE_INTERFACE_DATA interfaceData = new Native.SP_DEVICE_INTERFACE_DATA();

        if (!Native.SetupDiEnumDeviceInterfaces(_deviceInfoSet, null, ref _classGuid, index, interfaceData))
       {
             int error = Marshal.GetLastWin32Error();
             if (error != Native.ERROR_NO_MORE_ITEMS)
                 throw new Win32Exception(error);
             break;
         }

如果在32位架构上运行,那么一切都很好。

如果在64位架构上运行,那么SetupDiEnumDeviceInterfaces返回false,最后一次win错误等于1784。原因是在struct interfaceData字段中,cbSize没有64位体系结构的有效值(作为int别名Int32)。

来自官方文件

一个指向调用方分配缓冲区的指针,该缓冲区在成功返回时包含一个完整的DeviceInterfaceData结构,该结构标识满足搜索参数的接口。调用方必须在调用此函数之前将DeviceInterfaceData.cbSize设置为SP_DEVICE_INTERFACE_DATA。

尝试替换Int64类型的int(别名Int64)类型,用于字段: cbSize、devInt、保留。

如何将Guid类替换为64位体系结构?

如果我尝试简单地替换long类型的Guid:

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential)]
    internal class SP_DEVICE_INTERFACE_DATA 
    {
        internal Int64 cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA));
        internal long  interfaceClassGuid = 0; // temp
        internal Int64 flags = 1;
        internal Int64 reserved = 0;
    }

有了这样的结构定义,所有的功能都可以使用,但我失去了使用guid特殊类的方便。在类定义中,Guid还使用int类型,因此在64位体系结构上不会计算合适的大小。

EN

回答 2

Stack Overflow用户

发布于 2015-01-31 16:49:23

您可以尝试设置您的

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA

至:

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA

据我所读,Pack =8表示32位,Pack =1表示64位。

票数 1
EN

Stack Overflow用户

发布于 2014-11-10 19:35:20

问题不是您的GUID声明;SetupDiEnumDeviceInterfaces在64位平台上失败的原因是您没有在每个SP_DEVINFO_DATASP_DEVICE_INTERFACE_DATA上为reserved字段使用正确的数据类型。

SP_DEVINFO_DATASP_DEVICE_INTERFACE_DATA的结构定义表明,reserved字段被声明为UINT_PTR,这是一个指针类型。这些应该在您的P/Invoke类型中声明为IntPtr

(而且,您的所有int字段都应该定义为uint,因为这些字段映射到DWORD本机类型。)

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential)]
internal class SP_DEVINFO_DATA
{
    internal uint cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
    internal Guid classGuid;
    internal uint devInst;
    internal IntPtr reserved;
}

[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
    internal uint cbSize;
    internal short devicePath;
}

[StructLayout(LayoutKind.Sequential)]
internal class SP_DEVICE_INTERFACE_DATA 
{
    internal uint cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA));
    internal Guid interfaceClassGuid;
    internal uint flags;
    internal IntPtr reserved;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26851236

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档