c# - C# 上 64 位架构上的 SetupDiEnumDeviceInterfaces

标签 c# winapi 32bit-64bit

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

    [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;
    }

然后我调用这个函数如下:

        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,最后一次获胜错误等于 1784。 原因是在 struct interfaceData 字段中,cbSize 对于 64 位架构(作为 int 别名 Int32)没有有效值

来自官方文档

DeviceInterfaceData [out] A pointer to a caller-allocated buffer that contains, on successful return, a completed SP_DEVICE_INTERFACE_DATA structure that identifies an interface that meets the search parameters. The caller must set DeviceInterfaceData.cbSize to sizeof(SP_DEVICE_INTERFACE_DATA) before calling this function.

尝试将字段的 Int64 类型替换为 int 类型(别名 Int32):cbSize、devInt、reserved。

如何替换 64 位架构的类 Guid?

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

[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 位架构上计算正确的大小。

最佳答案

You need to use uint in all fields(not int), and IntPtr in Reserved field.

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SP_DEVINFO_DATA
{
    public uint cbSize;
    public Guid ClassGuid;
    public uint DevInst;
    public IntPtr Reserved;
}

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

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
    public uint cbSize;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
    public string DevicePath;
}

To set cbSize in code use this:

Win32.SP_DEVICE_INTERFACE_DATA did = new Win32.SP_DEVICE_INTERFACE_DATA();
did.cbSize = (uint)Marshal.SizeOf(did);

Win32.SP_DEVICE_INTERFACE_DETAIL_DATA didd = new Win32.SP_DEVICE_INTERFACE_DETAIL_DATA();
didd.cbSize = (uint)Marshal.SizeOf(didd);

关于c# - C# 上 64 位架构上的 SetupDiEnumDeviceInterfaces,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26851236/

相关文章:

c# - 如何从 DLL 访问带有接口(interface)的类?

c# - 如何解压缩 dotnet 核心中的存档?

c# - 使用 WebAdministration 管理单元从 .NET 运行 Powershell 脚本

c# - 双核性能不如单核?

c# - 从主 UI 线程上的按钮挂起子线程

c++ - 调整 token 权限 : ERROR_NOT_ALL_ASSIGNED after success

c++ - 在 Windows XP 中以编程方式旋转显示? (C++/Qt 和 WindowsAPI)

c++ - 如何在 Win32 应用程序中填充文件夹浏览器

java - 为什么当我在 64 位 jvm 中打开带有小程序的页面时 IE 11 会崩溃,但在 32 位 jvm 中却可以正常工作?

windows - Python 看不到 C :\Windows\System32\GroupPolicy 中的文件或文件夹