我正在尝试访问有关与C#中的设备使用win32 APIs相关的驱动程序的信息。
我设法启用/禁用设备(所以我检索句柄似乎确定),但是我没有运气时试图调用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);
这一点很重要,因为它指定它需要从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 / Charset=Charset.Unicode加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; };