[英]SetupDiEnumDeviceInterfaces on 64bit architecture on C#
I try to call Window API function SetupDiEnumDeviceInterfaces from C# on 64bits architecture. 我尝试在64位体系结构上从C#调用Window API函数SetupDiEnumDeviceInterfaces 。 I import function and declare additional structures.
我导入函数并声明其他结构。
[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;
}
Then I call this function as follows: 然后我按如下方式调用此函数:
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;
}
If runnig on 32bits architecture then all is well. 如果在32位架构上运行,那么一切都很好。
If runnig on 64bits architecture then SetupDiEnumDeviceInterfaces return false with last win error equal 1784. The reason is that in struct interfaceData field cbSize has not valid value for 64bits architecture(as int alias Int32). 如果在64位体系结构上运行runnig,则SetupDiEnumDeviceInterfaces返回false,最后一次取胜错误等于1784。原因是在struct interfaceData字段中, cbSize对于64位体系结构没有有效值 (如int别名Int32)。
From official documentation 从官方文件
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.
DeviceInterfaceData [out]指向分配给调用方的缓冲区的指针,该缓冲区包含成功返回时已完成的SP_DEVICE_INTERFACE_DATA结构,该结构标识满足搜索参数的接口。 The caller must set DeviceInterfaceData.cbSize to sizeof(SP_DEVICE_INTERFACE_DATA) before calling this function.
调用此函数之前,调用者必须将DeviceInterfaceData.cbSize设置为sizeof(SP_DEVICE_INTERFACE_DATA)。
Trying to replace the type int(alias Int32) of the type Int64 for fields: cbSize, devInt, reserved. 尝试将以下字段的类型替换为Int64类型的int(别名Int32):cbSize,devInt,保留。
How Can I replace class Guid for 64bits architecture? 如何替换64位体系结构的Guid类?
If I try replace Guid simply of the type long: 如果我尝试简单地替换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;
}
With such a structure definition all works but I lose the convenience of working with a special class for guid. 有了这样的结构定义,所有的作品都可以使用,但是我失去了为guid使用特殊类的便利。 In the class definition Guid also used the type int so the right size will not be calculated on 64bits architecture.
Guid在类定义中还使用了int类型,因此在64位体系结构上不会计算出正确的大小。
The problem is not your GUID declarations; 问题不在于您的GUID声明。 the reason
SetupDiEnumDeviceInterfaces
is failing out on 64-bit platforms is that you're not using the correct data type for the reserved
field on each of SP_DEVINFO_DATA
and SP_DEVICE_INTERFACE_DATA
. SetupDiEnumDeviceInterfaces
在64位平台上出现故障的原因是,您没有为SP_DEVINFO_DATA
和SP_DEVICE_INTERFACE_DATA
的reserved
字段使用正确的数据类型。
The structure definitions for SP_DEVINFO_DATA
and SP_DEVICE_INTERFACE_DATA
show that the reserved
fields are declared as UINT_PTR
, which is a pointer type. SP_DEVINFO_DATA
和SP_DEVICE_INTERFACE_DATA
的结构定义表明, reserved
字段被声明为UINT_PTR
,这是一种指针类型。 These should be declared in your P/Invoke types as IntPtr
. 这些应该在您的P / Invoke类型中声明为
IntPtr
。
(Also, all of your int
fields should instead be defined as uint
, as those fields map to the DWORD
native type.) (此外,应该将所有
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;
}
You might try setting your 您可以尝试设置
[StructLayout(LayoutKind.Sequential, Pack = 2)]
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
to: 至:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
From what I've read, Pack = 8 for 32 bit, Pack = 1 for 64 bit. 根据我的阅读,Pack = 8 for 32 bit,Pack = 1 for 64 bit。
You need to use
uint in all fields(not
int ), and
IntPtr in
Reserved field.
您需要在所有字段(不是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;
}
To set
cbSize in code use this:
要在代码中设置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.