SetupDiEnumDriverInfo总是返回错误259(没有更多可用数据)
SetupDiEnumDriverInfo always return with Error 259 (No more Data available)
我正在尝试使用win32 API访问与C#中的设备相关的驱动程序的信息。
我已经设法启用/禁用了设备(所以我检索的句柄看起来还可以),但在尝试调用SetupDiEnumDriverInfo时运气不佳。
这是我正在使用的代码:
private List<String> ListCompatibleDrivers(IntPtr hDevInfo, SP_DEVINFO_DATA devInfoData)
{
List<String> result = new List<String>();
try
{
SP_DRVINFO_DATA drvInfo = new SP_DRVINFO_DATA();
for (int i = 0; SetupDiEnumDriverInfo(hDevInfo, devInfoData, SPDIT_CLASSDRIVER, i, drvInfo); i++)
{
result.Add(drvInfo.Description);
}
if (result.Count < 1)
{
result.Add(Marshal.GetLastWin32Error().ToString());
}
return result;
}
catch
{
throw;
}
}
在可以假设参数正常的情况下(正如我所说,来自设置API的其他方法成功地使用了它们)。
这些是可能已损坏的结构和DllImport:
[StructLayout(LayoutKind.Sequential)]
public class SP_DRVINFO_DATA
{
public Int32 cbSize;
public Int32 driverType;
public UIntPtr reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
public String description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
public String mfgName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=256)]
public String providerName;
public FILETIME driverDate;
public Int64 driverVersion;
};
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiEnumDriverInfo(IntPtr lpInfoSet, SP_DEVINFO_DATA deviceInfoData, UInt32 driverType, Int32 memberIndex, SP_DRVINFO_DATA driverInfoData);
API调用立即返回false,Marshal.GetLastWin32Error().ToString()
返回259
,即ERROR_NO_MORE_ITEMS
。
我只是不明白,我的希望很高,我只是犯了一些愚蠢的错误,我看不见,因为我最近除了msdn什么都没读过,而且它变得非常累。。。
非常感谢任何帮助,非常感谢!
最重要的是,我可以告诉你,你与函数签名不匹配,应该是:
[DllImport("setupapi.dll", SetLastError = true, charset=Charset.Unicode)]
[return:MarshalAs(UnmanagedType.Bool)]
private static extern bool SetupDiEnumDriverInfo(
[In] IntPtr lpInfoSet,
[In, Optional] SP_DEVINFO_DATA deviceInfoData,
[In] UInt32 driverType,
[In] Int32 memberIndex,
[Out] out SP_DRVINFO_DATA driverInfoData);
这个out很重要,因为它指定需要从PInvoke中取出数据。
结构有几个问题,最烦人的是必须指定pack=4,这样本机代码才能找到正确的入口点。
这是有效的:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 4)]
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public UInt32 Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string MfgName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ProviderName;
public System.Runtime.InteropServices.ComTypes.FILETIME DriverDate;
public long DriverVersion;
}
当然,在p/Invokes前面加上Charset=Charset.Unicode
也是一个好主意。
以下是在x64和x86上都工作的API和结构定义。我还添加了SetupDiGetDriverInfoDetail,很有可能你也需要它
API:
DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetupDiGetDriverInfoDetail(
IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
ref SP_DRVINFO_DATA DriverInfoData,
ref SP_DRVINFO_DETAIL_DATA DriverInfoDetailData,
Int32 DriverInfoDetailDataSize,
ref Int32 RequiredSize);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetupDiEnumDriverInfo(
IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData,
int DriverType,
int MemberIndex,
ref SP_DRVINFO_DATA DriverInfoData);
结构:
#if !WIN64
[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Unicode)]
#else
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)]
#endif
public struct SP_DRVINFO_DATA
{
public int cbSize;
public uint DriverType;
public UIntPtr Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string MfgName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ProviderName;
public System.Runtime.InteropServices.ComTypes.FILETIME DriverDate;
public ulong DriverVersion;
}
#if !WIN64
[StructLayout(LayoutKind.Sequential, Pack = 2, CharSet = CharSet.Unicode)]
#else
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Unicode)]
#endif
public 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;
};
相关文章:
- 使用JsonCpp将数据返回到带有pybind11的python会在python调用中产生Symbol not foun
- 从函数返回任意简单类型的数据
- 通过 NIF 从C++返回自定义数据结构
- 为什么我们使用在C++中返回数据结构的函数?
- 将传入的网络"char*"数据转换为"uint8_t"并返回的安全方法是什么?
- 如何在模板中返回正确类型的数据?
- H5Tget_member_type() 返回复合 HDF5 数据类型的奇怪值
- 保持排序的数据结构,允许log N插入时间,并且可以返回我在log N中查找的元素的索引
- 如何通过另一个对象中的命令正确地从一个对象返回数据
- 查找存储在二叉搜索树的所有非叶子中的数据总和?(返回整数的独立递归函数
- 在C++中,运算符 sizeof 返回什么数据类型?
- 函数重载并根据相同的输入返回不同的数据类型
- 从新实例的向量中检索数据返回 0
- 类类型中的访问器函数未从 C++ 中的私有数据返回正确的值
- c++ 函数,将数据返回到引用向量
- UNIX域套接字C++服务器无法将数据返回到客户端
- 获取和设置内部数据:返回类型,错误情况下的行为
- 存储在char数组中的双精度数据返回浮点值
- QtCreator QMediaPlayer元数据返回空白QString
- 直接使用变量(数组中的数据返回相同)或与指针一起使用