我尝试在 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/