【发布时间】:2015-01-07 04:41:51
【问题描述】:
我尝试在 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] 指向调用者分配的缓冲区的指针 成功返回时包含完整的 SP_DEVICE_INTERFACE_DATA 标识满足搜索的接口的结构 参数。调用者必须将 DeviceInterfaceData.cbSize 设置为 调用此函数之前的 sizeof(SP_DEVICE_INTERFACE_DATA)。
尝试将 int64 类型的 int 类型(别名 Int32)替换为字段:cbSize、devInt、保留。
如何替换 64 位架构的类 Guid?
如果我尝试将 Guid 替换为 long 类型:
[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 位架构上计算正确的大小。
【问题讨论】:
标签: c# winapi 32bit-64bit