SetupDiEnumDriverInfo始终返回错误259(没有更多数据可用)

时间:2013-06-27 13:34:35

标签: c# c++ windows winapi driver

我正在尝试使用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()返回259ERROR_NO_MORE_ITEMS

我只是没有得到它,我的希望很高我只是犯了一些我无法看到的愚蠢的错误,因为我最近几乎没有读过任何东西,而且它得到了令人难以置信的疲惫...

非常感谢任何帮助,非常感谢!

3 个答案:

答案 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;
        };