我正在尝试使用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
。
我只是没有得到它,我的希望很高我只是犯了一些我无法看到的愚蠢的错误,因为我最近几乎没有读过任何东西,而且它得到了令人难以置信的疲惫...
非常感谢任何帮助,非常感谢!
答案 0 :(得分:1)
从顶部开始,我可以告诉你,你应该与功能签名不匹配:
[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);
这很重要,因为它指定它需要从PInvoke中撤回数据。
答案 1 :(得分:1)
结构有几个问题,最令人讨厌的是必须指定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;
}
当然,使用Charset=Charset.Unicode
为P / Invokes加上前缀也是一个上帝的想法。
答案 2 :(得分:0)
以下是适用于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;
};