[英]SetupDiEnumDeviceInterfaces on 64bit architecture on C#
我嘗試在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位體系結構上運行runnig,則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類?
如果我嘗試簡單地替換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位體系結構上不會計算出正確的大小。
問題不在於您的GUID聲明。 SetupDiEnumDeviceInterfaces
在64位平台上出現故障的原因是,您沒有為SP_DEVINFO_DATA
和SP_DEVICE_INTERFACE_DATA
的reserved
字段使用正確的數據類型。
SP_DEVINFO_DATA
和SP_DEVICE_INTERFACE_DATA
的結構定義表明, reserved
字段被聲明為UINT_PTR
,這是一種指針類型。 這些應該在您的P / Invoke類型中聲明為IntPtr
。
(此外,應該將所有int
字段都定義為uint
,因為這些字段映射到DWORD
本機類型。)
[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;
}
您可以嘗試設置
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
至:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
根據我的閱讀,Pack = 8 for 32 bit,Pack = 1 for 64 bit。
您需要在所有字段(不是int )中使用uint ,在保留字段中使用IntPtr 。
[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;
}
要在代碼中設置cbSize ,請使用以下命令:
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.