我正在嘗試進入SetupApi的一些調用。我特別遇到SetupDiGetDeviceInterfaceDetail()
的問題。編組爲本地代碼時緩衝區大小不正確
這裏是我的本地方法的定義:
class NativeMethods {
[DllImport("SetupApi.dll", SetLastError = true)]
[return : MarshalAs(UnmanagedType.Bool)]
public static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr hDevs,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
uint deviceInterfaceDetailDataSize,
ref uint requiredSize,
ref SP_DEVINFO_DATA deviceInfoData);
}
下面是結構的原生對管理的定義涉及:
[StructLayout(LayoutKind.Sequential, Size = 0x10)]
public struct GUID
{
public Int32 Data1;
public Int16 Data2;
public Int16 Data3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data4;
public GUID(Int32 d1, Int16 d2, Int16 d3, byte[] d4)
{
Data1 = d1;
Data2 = d2;
Data3 = d3;
Data4 = new byte[8];
Array.Copy(d4, Data4, d4.Length);
}
}
typedef struct _SP_DEVINFO_DATA {
DWORD cbSize;
GUID ClassGuid;
DWORD DevInst; // DEVINST handle
ULONG_PTR Reserved;
} SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
[StructLayout(LayoutKind.Sequential)]
struct SP_DEVINFO_DATA
{
public uint cbSize;
public GUID ClassGuid;
public uint DevInst;
public UIntPtr Reserved;
}
typedef struct _SP_DEVICE_INTERFACE_DATA {
DWORD cbSize;
GUID InterfaceClassGuid;
DWORD Flags;
ULONG_PTR Reserved;
} SP_DEVICE_INTERFACE_DATA, *PSP_DEVICE_INTERFACE_DATA;
[StructLayout(LayoutKind.Sequential)]
struct SP_DEVICE_INTERFACE_DATA
{
public uint cbSize;
public GUID InterfaceClassGuid;
public uint Flags;
public UIntPtr Reserved;
}
typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA_A {
DWORD cbSize;
CHAR DevicePath[ANYSIZE_ARRAY];
} SP_DEVICE_INTERFACE_DETAIL_DATA_A, *PSP_DEVICE_INTERFACE_DETAIL_DATA_A;
[StructLayout(LayoutKind.Sequential)]
struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public uint cbSize;
public IntPtr devicePath;
}
等待最後的結構,我看了以前的帖子在這裏,表示定義爲SP_DEVICE_INTERFACE_DETAIL_DATA的結構具有可變長度數組,C#結構應該使用IntPtr。爲此,我通過Marshal.AllocHGlobal()分配內存,如下所示。下面是我如何使用SetupDiGetDeviceInterfaceDetail():
uint requiredSize = 0; // is ignored in this usage
byte[] foo = new byte[1024];
SP_DEVINFO_DATA spDevInfoData = new SP_DEVINFO_DATA();
spDevInfoData.cbSize = (uint)Marshal.SizeOf(spDevInfoData);
SP_DEVICE_INTERFACE_DATA spDevInfData = new SP_DEVICE_INTERFACE_DATA();
spDevInfData.cbSize = (uint)Marshal.SizeOf(spDevInfData);
SP_DEVICE_INTERFACE_DETAIL_DATA spDevInfDetailData = new SP_DEVICE_INTERFACE_DETAIL_DATA();
spDevInfDetailData.cbSize = 5; // the size needs to be 5
spDevInfDetailData.devicePath = Marshal.AllocHGlobal(foo.Length);
NativeMethods.SetupDiGetDeviceInterfaceDetail(devList,
ref spDevInfData,
ref spDevInfDetailData,
spDevInfDetailData.cbSize,
ref requiredSize,
ref spDevInfoData);
我使用SetupDiGetClassDevs()和SetupDiEnumDeviceInterfaces()我SetupDiGetDeviceInterfaceDetail的使用()之前進行。在這兩種情況下,這些方法都有效。我提供了第一個函數的設備列表,並使用枚舉調用遍歷列表。
但是,當我調用SetupDiGetDeviceInterfaceDetail()時,函數失敗,並且Win32 GetLastError()返回122的錯誤,我發現它是:ERROR_INSUFFICIENT_BUFFER。我看不出爲什麼我的緩衝區不夠大小。我基本上正在做我在C++「測試應用程序」中做的事情,因爲我無法在C#中使用它。在該應用程序中,我使用分配給SP_DEVICE_INTERFACE_DETAIL_DATA結構的char [] array 1024成員。這就是爲什麼我在C#中使用1024位字節數組成員。
任何幫助或見解都非常感謝。
之後你看過'requiredSize'嗎? – ordag