我正在尝试从 C# 应用程序调用 SetupDiGetDriverInfoDetail。调用失败,我返回的 win32 错误是 0x6F8(“提供的用户缓冲区对于请求的操作无效。”)。到目前为止,我已经能够成功调用其他 setupdi 函数,所以我认为问题在于我编码函数或 SP_DRVINFO_DETAIL_DATA 结构的方式。
我不确定,但我认为问题可能出在 SP_DRVINFO_DETAIL_DATA 结构的 HardwareID 成员上。我试过将 HardwareID 指定为不同的类型(例如字节数组并在设置大小和调用函数之前分配缓冲区),但总是出现相同的错误。如果有人对此调用有任何经验或有任何指示,我将不胜感激。
下面是我的结构定义、函数导入和代码片段。在此版本中,我使用固定大小的 HardwareID 缓冲区。我还尝试将缓冲区大小指定为 1,期望出现“缓冲区太小”错误,但我总是收到“无效缓冲区”错误。
[DllImport("setupapi.dll", SetLastError = true)]
internal static extern Int32 SetupDiGetDriverInfoDetail(
IntPtr DeviceInfoSet,
SP_DEVINFO_DATA DeviceInfoData,
SP_DRVINFO_DATA DriverInfoData,
ref SP_DRVINFO_DETAIL_DATA DriverInfoDetailData,
Int32 DriverInfoDetailDataSize,
ref Int32 RequiredSize);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct SP_DRVINFO_DETAIL_DATA
{
public Int32 cbSize;
public System.Runtime.InteropServices.ComTypes.FILETIME InfDate;
public Int32 CompatIDsOffset;
public Int32 CompatIDsLength;
public IntPtr Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public String SectionName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public String InfFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public String DrvDescription;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public String HardwareID;
};
SetupApiWrapper.SP_DRVINFO_DETAIL_DATA DriverInfoDetailData = new SetupApiWrapper.SP_DRVINFO_DETAIL_DATA();
DriverInfoDetailData.cbSize = Marshal.SizeOf(DriverInfoDetailData);
result = SetupApiWrapper.SetupDiGetDriverInfoDetail(
DevInfo,
DeviceInfoData,
DriverInfoData,
ref DriverInfoDetailData,
DriverInfoDetailData.cbSize,
ref reqSize);
最佳答案
o虽然我同意错误代码似乎出乎意料,但我认为问题在于 cbSize 应该设置为 sizeof(SP_DRVINFO_DETAIL_DATA)(这是正确的 C sizeof,而不是 p/invoke 结构上的 Marshal.SizeOf。)
使用两行 C 程序的快速测试给出:
ANSI 797
UNICODE 1570
对于两个合适的sizeof值(你需要自己算出你需要哪个...)
相比之下,Marshal.SizeOf(typeof(SP_DRVINFO_DETAIL_DATA))
为您的结构提供 1048 作为长度。
我认为你需要在继续之前把它排好。
我怀疑可能是DriverInfoDetailDataSize太小会返回buffer-too-small错误,但cbSize不对会返回invalid-buffer错误。
SetupDiGetDriverInfoDetail 的帮助也明确指出 cbSize 和 DriverInfoDetailDataSize 不应该是相同的值(因为 ANYSIZE_ARRAY 只是定义为 1 作为占位符),所以您不应该期望 Marshal.SizeOf 可以正确地与您一起工作故意超大的结构。
补充更正:
您的 InfFilename 成员的长度也是错误的 - 与 SETUPAPI.H 中的结构完全匹配的结构是:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet=CharSet.Unicode)]
internal struct SP_DRVINFO_DETAIL_DATA
{
public Int32 cbSize;
public System.Runtime.InteropServices.ComTypes.FILETIME InfDate;
public Int32 CompatIDsOffset;
public Int32 CompatIDsLength;
public IntPtr Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public String SectionName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public String InfFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public String DrvDescription;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1)]
public String HardwareID;
};
这给出了正确的长度,无论是在 ANSI 还是 UNICODE 版本中。但是,您不想按原样使用它,因为您需要 HardwareID 更长,所以您必须调整它的长度,然后忍受 Marshal.SizeOf 给出错误的值以直接插入 cbSize。
关于c# - 使用 SetupDiGetDriverInfoDetail 调用 PInvoke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5120371/