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

C# SetupDiEnumDriverInfo始终返回错误259(没有更多可用数据),c#,c++,windows,winapi,driver,C#,C++,Windows,Winapi,Driver,我正在尝试使用win32 API访问与C#中的设备相关联的驱动程序的信息 我已经成功地启用/禁用了设备(因此我正在检索的句柄似乎没有问题),但是在尝试调用SetupDiEnumDriverInfo时,我运气不佳 这是我正在使用的代码: 私有列表兼容驱动程序(IntPtr hDevInfo、SP\u DEVINFO\u DATA DEVINFO) { 列表结果=新列表(); 尝试 { SP_DRVINFO_DATA DRVINFO=新的SP_DRVINFO_DATA(); 对于(int i=0;S

我正在尝试使用win32 API访问与C#中的设备相关联的驱动程序的信息

我已经成功地启用/禁用了设备(因此我正在检索的句柄似乎没有问题),但是在尝试调用SetupDiEnumDriverInfo时,我运气不佳

这是我正在使用的代码:

私有列表兼容驱动程序(IntPtr hDevInfo、SP\u DEVINFO\u DATA DEVINFO)
{
列表结果=新列表();
尝试
{
SP_DRVINFO_DATA DRVINFO=新的SP_DRVINFO_DATA();
对于(int i=0;SetupDiEnumDriverInfo(hDevInfo、devinfo数据、SPDIT_类驱动程序、i、drvInfo);i++)
{
结果.添加(drvInfo.说明);
}
如果(result.Count<1)
{
Add(Marshal.GetLastWin32Error().ToString());
}
返回结果;
}
抓住
{
投掷;
}
}
其中,可以假定参数是正确的(正如我所说,setupapi中的其他方法也成功地使用了它们)

以下是可能已损坏的结构和DllImport:

[StructLayout(LayoutKind.Sequential)]
公共类SP_DRVINFO_数据
{
公共Int32 cbSize;
公共Int32驱动器类型;
保留公共UIntPtr;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=256)]
公共字符串描述;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=256)]
公共字符串mfgName;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=256)]
公共字符串提供者名称;
公共文件时间驱动数据;
公共Int64驱动服务器;
};
[DllImport(“setupapi.dll”,SetLastError=true)]
公共静态外部bool SetupDiEnumDriverInfo(IntPtr lpInfoSet、SP_DEVINFO_数据设备infodata、UInt32驱动器类型、Int32成员索引、SP_DRVINFO_数据驱动器fodata);
API调用立即返回false,
Marshal.GetLastWin32Error().ToString()
返回
259
,即
ERROR\u NO\u MORE\u ITEMS

我只是不明白,我的希望很高,我只是犯了一些愚蠢的错误,我看不到,因为我最近几乎没有读过任何东西,但msdn,它变得令人难以置信的累


非常感谢您的帮助,非常感谢

很好,我可以告诉你,你与函数签名不匹配,应该是:

[DllImport(“setupapi.dll”,SetLastError=true,charset=charset.Unicode)]
[返回:Marshallas(UnmanagedType.Bool)]
私有静态外部bool SetupDiEnumDriverInfo(
[In]IntPtr lpInfoSet,
[In,可选]SP_DeviceInfo_数据设备Info数据,
[In]UInt32驱动器类型,
[In]Int32 memberIndex,
[Out]Out SP_DRVINFO_数据驱动器RINFODATA);

这一点很重要,因为它指定需要从PInvoke中提取数据。

该结构有几个问题,最烦人的是必须指定pack=4,以便本机代码找到正确的入口点。
这是有效的:

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode,Pack=4)]
公共结构SP_DRVINFO_数据
{
公共机构的规模;
公共int-DriverType;
公共UInt32保留;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=256)]
公共字符串描述;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=256)]
公共字符串MfgName;
[Marshallas(UnmanagedType.ByValTStr,SizeConst=256)]
公共字符串提供者名称;
public System.Runtime.InteropServices.ComTypes.FILETIME DriverDate;
公共长距离驾驶;
}

当然,用
Charset=Charset.Unicode
作为p/Invokes的前缀也是一个好主意。

下面是在x64和x86上使用的API和结构定义。我还添加了SetupDiGetDriverInfo详细信息,很可能您也需要它

API:

结构:

#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;
        };

您是否尝试过在
DllImport
上设置
charset=charset.Unicode
标志?我尝试了
Auto
Ansi
Unicode
,但都没有解决我的问题。谢谢你的意见!您需要将cbSize设置为SP_DRVINFO_数据结构的大小。很好!我调整了!但这仍然不能解决问题。不过,非常感谢!谢谢,这肯定是我的代码中有一个错误的地方!然而,这并没有解决我的问题。不过,谢谢你的努力!枚举是否可能为空?您是否尝试过一个小型非托管控制台应用程序进行测试?我使用DevCon工具进行测试--我相信它们使用相同的API,并且我知道对于我正在测试的设备,肯定有多个驱动程序实例可用。您的结构似乎也错了,我已经根据MSDNI更新了我的答案,我认为您混淆了SP_DEVINFO_数据和SP_DRVINFO_数据
#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;
        };