.NET中如何判断已安装驱动是否为第三方驱动
获取第三方已安装驱动的两种实现方案(C#/.NET)
一、基于WMI的实现
核心判断逻辑是利用Win32_DriverPackage类的IsBuiltIn属性:
IsBuiltIn=True:驱动是Windows系统镜像(Install.wim)内置的原生驱动IsBuiltIn=False:驱动是Windows安装后另行安装的第三方驱动
如果需要关联到已加载的硬件驱动实例,可以结合Win32_PnPSignedDriver类,通过InfName属性关联驱动包与硬件实例。
C#代码示例(WMI)
using System.Management; public static List<ThirdPartyDriver> GetThirdPartyDriversViaWmi() { var thirdPartyDrivers = new List<ThirdPartyDriver>(); // 查询所有非内置驱动包 var driverPackageQuery = new ObjectQuery("SELECT * FROM Win32_DriverPackage WHERE IsBuiltIn = FALSE"); using (var searcher = new ManagementObjectSearcher(driverPackageQuery)) { foreach (ManagementObject package in searcher.Get()) { var infName = package["InfName"]?.ToString(); if (string.IsNullOrEmpty(infName)) continue; // 关联到已加载的PnP驱动实例(可选,用于获取硬件设备信息) var pnpQuery = new ObjectQuery($"SELECT * FROM Win32_PnPSignedDriver WHERE InfName = '{infName}'"); using (var pnpSearcher = new ManagementObjectSearcher(pnpQuery)) { foreach (ManagementObject pnpDriver in pnpSearcher.Get()) { thirdPartyDrivers.Add(new ThirdPartyDriver { DeviceName = pnpDriver["DeviceName"]?.ToString(), DriverProvider = pnpDriver["DriverProviderName"]?.ToString(), InfFileName = infName, DriverVersion = pnpDriver["DriverVersion"]?.ToString(), DeviceInstanceId = pnpDriver["DeviceInstanceId"]?.ToString() }); } } } } return thirdPartyDrivers; } public class ThirdPartyDriver { public string DeviceName { get; set; } public string DriverProvider { get; set; } public string InfFileName { get; set; } public string DriverVersion { get; set; } public string DeviceInstanceId { get; set; } }
注意:Win32_DriverPackage需要管理员权限才能完整枚举,部分受系统保护的驱动包可能无法访问。
二、基于SetupAPI.dll的实现
SetupAPI提供了更底层的驱动枚举能力,核心判断逻辑围绕驱动的来源路径和发布者展开:
- 非Microsoft发布的驱动直接判定为第三方驱动
- Microsoft发布的驱动,若其INF文件不在系统原生
%Windows%\inf目录(而在%Windows%\System32\DriverStore\FileRepository下的第三方目录),则判定为后期安装的更新驱动(属于用户定义的第三方范畴)
C#代码示例(SetupAPI)
using System; using System.Collections.Generic; using System.Runtime.InteropServices; public static class ThirdPartyDriverEnumerator { // SetupAPI P/Invoke 定义 [DllImport("setupapi.dll", SetLastError = true)] private static extern IntPtr SetupDiGetClassDevs(IntPtr classGuid, string enumerator, IntPtr hwndParent, uint flags); [DllImport("setupapi.dll", SetLastError = true)] private static extern bool SetupDiEnumDeviceInfo(IntPtr deviceInfoSet, uint memberIndex, ref SP_DEVINFO_DATA deviceInfoData); [DllImport("setupapi.dll", SetLastError = true)] private static extern bool SetupDiGetDeviceRegistryProperty(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, uint property, out uint propertyRegType, IntPtr propertyBuffer, uint propertyBufferSize, out uint requiredSize); [DllImport("setupapi.dll", SetLastError = true)] private static extern bool SetupDiEnumDriverInfo(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, uint driverType, uint memberIndex, ref SP_DRVINFO_DATA driverInfoData); [DllImport("setupapi.dll", SetLastError = true)] private static extern bool SetupDiGetDriverInfoDetail(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, ref SP_DRVINFO_DATA driverInfoData, ref SP_DRVINFO_DETAIL_DATA driverInfoDetailData, uint driverInfoDetailDataSize, out uint requiredSize); [DllImport("setupapi.dll", SetLastError = true)] private static extern bool SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet); // 结构体定义 [StructLayout(LayoutKind.Sequential)] private struct SP_DEVINFO_DATA { public uint cbSize; public Guid ClassGuid; public uint DevInst; public IntPtr Reserved; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct SP_DRVINFO_DATA { public uint cbSize; public uint DriverType; public IntPtr 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; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] private struct SP_DRVINFO_DETAIL_DATA { public uint cbSize; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string InfFileName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string InfSectionName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string HardwareId; } // 常量定义 private const uint DIGCF_ALLCLASSES = 0x00000004; private const uint DIGCF_PRESENT = 0x00000002; private const uint SPDRP_DEVICEDESC = 0x00000000; private const uint SPDIT_COMPATDRIVER = 0x00000000; public static List<ThirdPartyDriver> GetThirdPartyDriversViaSetupApi() { var thirdPartyDrivers = new List<ThirdPartyDriver>(); IntPtr deviceInfoSet = IntPtr.Zero; try { // 枚举所有已连接的设备 deviceInfoSet = SetupDiGetClassDevs(IntPtr.Zero, null, IntPtr.Zero, DIGCF_ALLCLASSES | DIGCF_PRESENT); if (deviceInfoSet == IntPtr.Zero) throw new System.ComponentModel.Win32Exception(); SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA(); deviceInfoData.cbSize = (uint)Marshal.SizeOf(deviceInfoData); for (uint deviceIndex = 0; SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, ref deviceInfoData); deviceIndex++) { // 获取设备名称 string deviceName = GetDeviceProperty(deviceInfoSet, ref deviceInfoData, SPDRP_DEVICEDESC); if (string.IsNullOrEmpty(deviceName)) continue; // 枚举设备的兼容驱动 SP_DRVINFO_DATA driverInfoData = new SP_DRVINFO_DATA(); driverInfoData.cbSize = (uint)Marshal.SizeOf(driverInfoData); for (uint driverIndex = 0; SetupDiEnumDriverInfo(deviceInfoSet, ref deviceInfoData, SPDIT_COMPATDRIVER, driverIndex, ref driverInfoData); driverIndex++) { string infPath = GetDriverInfPath(deviceInfoSet, ref deviceInfoData, ref driverInfoData); if (string.IsNullOrEmpty(infPath)) continue; // 判断是否为第三方驱动 bool isThirdParty = false; if (!driverInfoData.ProviderName.Equals("Microsoft", StringComparison.OrdinalIgnoreCase)) { isThirdParty = true; } else { // 微软发布的驱动,检查是否为系统内置INF string systemInfPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\inf\"; if (!infPath.StartsWith(systemInfPath, StringComparison.OrdinalIgnoreCase)) { isThirdParty = true; } } if (isThirdParty) { thirdPartyDrivers.Add(new ThirdPartyDriver { DeviceName = deviceName, DriverProvider = driverInfoData.ProviderName, DriverVersion = ConvertDriverVersion(driverInfoData.DriverVersion), InfFileName = System.IO.Path.GetFileName(infPath) }); } } } } finally { if (deviceInfoSet != IntPtr.Zero) { SetupDiDestroyDeviceInfoList(deviceInfoSet); } } return thirdPartyDrivers; } private static string GetDeviceProperty(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, uint propertyId) { uint requiredSize = 0; SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, propertyId, out _, IntPtr.Zero, 0, out requiredSize); if (requiredSize == 0) return null; IntPtr buffer = Marshal.AllocHGlobal((int)requiredSize); try { if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, propertyId, out _, buffer, requiredSize, out _)) { return Marshal.PtrToStringUni(buffer); } return null; } finally { Marshal.FreeHGlobal(buffer); } } private static string GetDriverInfPath(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA deviceInfoData, ref SP_DRVINFO_DATA driverInfoData) { uint requiredSize = 0; SP_DRVINFO_DETAIL_DATA detailData = new SP_DRVINFO_DETAIL_DATA(); detailData.cbSize = (uint)Marshal.SizeOf(detailData); SetupDiGetDriverInfoDetail(deviceInfoSet, ref deviceInfoData, ref driverInfoData, ref detailData, detailData.cbSize, out requiredSize); if (SetupDiGetDriverInfoDetail(deviceInfoSet, ref deviceInfoData, ref driverInfoData, ref detailData, requiredSize, out _)) { return detailData.InfFileName; } return null; } private static string ConvertDriverVersion(ulong version) { ushort major = (ushort)((version >> 48) & 0xFFFF); ushort minor = (ushort)((version >> 32) & 0xFFFF); ushort build = (ushort)((version >> 16) & 0xFFFF); ushort revision = (ushort)(version & 0xFFFF); return $"{major}.{minor}.{build}.{revision}"; } } public class ThirdPartyDriver { public string DeviceName { get; set; } public string DriverProvider { get; set; } public string DriverVersion { get; set; } public string InfFileName { get; set; } }
三、验证逻辑准确性
可以通过对比Get-WindowsDriver -Online(无-All参数)的输出结果来验证,两种方案枚举的第三方驱动列表应与PowerShell命令输出一致。
内容的提问来源于stack exchange,提问作者ElektroStudios
相关产品推荐
相关产品推荐

