在C#或VB.NET中,我想检索第三方安装的驱动程序列表。只有第三方司机。
我发现了这些WMI类,我认为可以从这些类中检索所有已安装的驱动程序和有用的信息,包括目录路径:SystemDriver、PnPSignedDriver、PnPEntity、PnPSignedDriverCIMDataFile。
但我不知道如何确定司机是第三方司机还是第三方司机。
我的问题是:如果能够从Win32_PnPSignedDriver类中识别已安装的驱动程序(例如,它的ClassGuid属性),如何确定该特定驱动程序是第三方驱动程序还是非第三方驱动程序?
所谓第三方驱动程序,我指的是没有内置到Windows映像(Install.wim)中的驱动程序。它是在安装Windows之后下载和安装的任何驱动程序。
例如,所有这些都是我安装的第三方驱动程序:
我发现PowerShell的Get-WindowsDriver cmdlet用于列出所有已安装的驱动程序(驱动程序名称、类型、版本、路径等),并且它具有-All参数:
-All 显示有关默认驱动程序的信息。如果不指定此参数,则只列出第三方驱动程序和列表.
如果未指定-All参数,则只列出已安装的第三方驱动程序.
同样,我发现这些程序只会导出/备份第三方安装的驱动程序:
dism.exe /online /导出驱动程序/destination:“文件夹的完整路径”pnputil.exe /export*“文件夹的完整路径”
我还找到了带有P/ setupapi.dll,调用的这个C#代码示例,但我不确定这个API是否提供了一个函数来确定驱动程序是否是第三方。
对我来说,最简单的解决方案是运行和解析Get-WindowsDriver cmdlet输出,但我真的想深入了解WMI (或从setupapi.dll导出的函数),以便能够模仿Get-WindowsDriver,的相同输出,为此,我需要了解如何确定何时安装了驱动程序--它是第三方驱动程序,何时不是。
发布于 2022-10-06 02:42:28
由于我无法使用WMI或Windows获得解决方案,所以我转向了集成Powershell。
所需的包:
注意:我认为至少需要.net 5.0 (相关的PowerShell Nuget包的7.1.7版本)才能运行它。我用Get-WindowsDriver包在.NET Framework4.8中尝试了它,但是它找不到Microsoft.PowerShell.5.ReferenceAssemblies
cmdlet。
还要考虑到这是我第一次使用这些PowerShell自动化API。可能相关的PowerShell自动化代码没有得到适当的优化。
首先,这两个枚举和一个类将用于代表司机的信息:
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.IO
Imports System.Management.Automation
Imports System.Management.Automation.Runspaces
Imports System.Text
Imports Microsoft.PowerShell
''' <summary>
''' Specifies the behavior to get a driver when calling the <see cref="GetSystemDrivers()"/> function.
''' </summary>
<Flags>
Public Enum GetDriverFlags As Short
''' <summary>
''' Get those drivers that are commonly known as default drivers.
''' <para></para>
''' These drivers are included on the Windows distribution media
''' and therefore are automatically installed as part of Windows.
''' <para></para>
''' This is the opposite behavior to <see cref="GetDriverFlags.NotInbox"/> flag.
''' </summary>
Inbox = 1 << 0
''' <summary>
''' Get those drivers that are commonly known as third-party drivers.
''' <para></para>
''' These drivers are not included on the Windows distribution media
''' and therefore are not automatically installed as part of Windows.
''' <para></para>
''' This is the opposite behavior to <see cref="GetDriverFlags.Inbox"/> flag.
''' </summary>
NotInbox = 1 << 1
''' <summary>
''' Get all the drivers (inbox and not-inbox drivers).
''' </summary>
Any = GetDriverFlags.Inbox Or GetDriverFlags.NotInbox
End Enum
''' <summary>
''' Specifies the signature status of a driver.
''' <para></para>
''' This enum is used in <see cref="DismDriverInfo.Signature"/> property.
''' </summary>
Public Enum DismDriverSignature As Integer
''' <summary>
''' The signature status of the driver is unknown.
''' <para></para>
''' DISM only checks for a valid signature for boot-critical drivers.
''' </summary>
Unknown = 0
''' <summary>
''' The driver is unsigned.
''' </summary>
Unsigned = 1
''' <summary>
''' The driver is signed.
''' </summary>
Signed = 2
End Enum
''' <summary>
''' Represents basic information for a installed system driver.
''' </summary>
<Serializable>
Public Class DismDriverInfo
#Region " Notes and research informartion "
' - DismDriverPackage structure:
' https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/dism/dismdriverpackage-structure
' - Useless DISM object properties that were not implemented in this class:
'
' Path, WinPath, SysDrivePath, ScratchDirectory, LogPath, LogLevel,
' MajorVersion, MinorVersion, Build, Revision
' (those can be accessed via the "DismDriverInfo.Version" property)
#End Region
#Region " Properties "
''' <summary>
''' Gets the provider of the driver.
''' </summary>
Public ReadOnly Property Provider As String
''' <summary>
''' Gets the class name of the driver.
''' </summary>
Public ReadOnly Property ClassName As String
''' <summary>
''' Gets the description of the driver class.
''' <para></para>
''' Note: the description is spelled using the current system language.
''' </summary>
Public ReadOnly Property ClassDescription As String
''' <summary>
''' Gets the class global unique identifier (GUID) of the driver.
''' </summary>
Public ReadOnly Property ClassGuid As Guid
''' <summary>
''' Gets the .inf file name of the driver.
''' </summary>
Public ReadOnly Property DriverFile As String
''' <summary>
''' Gets the driver version.
''' </summary>
Public ReadOnly Property Version As Version
''' <summary>
''' Gets the manufacturer's build date of the driver.
''' </summary>
Public ReadOnly Property BuildDate As Date
''' <summary>
''' Gets a value that indicates the driver signature status.
''' </summary>
Public ReadOnly Property Signature As DismDriverSignature
''' <summary>
''' Gets a value indicating whether the driver is included on the Windows distribution media
''' and automatically installed as part of Windows.
''' </summary>
Public ReadOnly Property Inbox As Boolean
''' <summary>
''' Gets a value indicating whether the driver is located on the operating system
''' that is currently running on the local computer.
''' </summary>
Public ReadOnly Property Online As Boolean
''' <summary>
''' Gets a value indicating whether the driver is boot-critical.
''' </summary>
Public ReadOnly Property BootCritical As Boolean
''' <summary>
''' Gets a value indicating whether the computer needs to be restarted to complete driver install/uninstall.
''' </summary>
Public ReadOnly Property RestartRequired As Boolean
''' <summary>
''' Gets the catalog file for the driver.
''' </summary>
Public ReadOnly Property CatalogFile As String
''' <summary>
''' Gets the original file name of the driver.
''' </summary>
Public ReadOnly Property OriginalFileName As String
''' <summary>
''' Gets the driver directory.
''' </summary>
Public ReadOnly Property Directory As DirectoryInfo
Get
Return New DirectoryInfo(IO.Path.GetDirectoryName(Me.OriginalFileName))
End Get
End Property
#End Region
#Region " Private Fields "
''' <summary>
''' A reference to the underlying <see cref="PSObject"/> object of type: "Microsoft.Dism.Commands.BasicDriverObject".
''' </summary>
Private ReadOnly dismDriverObject As PSObject
#End Region
#Region " Constructors "
''' <summary>
''' Prevents a default instance of the <see cref="DismDriverInfo"/> class from being created.
''' </summary>
<DebuggerNonUserCode>
Private Sub New()
End Sub
''' <summary>
''' Initializes a new instance of the <see cref="DismDriverInfo"/> class.
''' </summary>
''' <param name="dismDriverObject">
''' A <see cref="PSObject"/> object whose <see cref="PSObject.BaseObject"/> property
''' is of type: "Microsoft.Dism.Commands.BasicDriverObject"
''' <para></para>
''' This object is obtained from the return value of a call to <see cref="PowerShell.Invoke()"/> function
''' that invoked the PowerShell's 'Get-WindowsDriver' cmdlet.
''' </param>
''' <remarks>
''' Get-WindowsDriver cmdlet reference:
''' <see href="https://learn.microsoft.com/en-us/powershell/module/dism/get-windowsdriver"/>
''' </remarks>
<DebuggerStepThrough>
Public Sub New(dismDriverObject As PSObject)
If Not dismDriverObject.BaseObject?.GetType().FullName.Equals("Microsoft.Dism.Commands.BasicDriverObject", StringComparison.Ordinal) Then
Throw New ArgumentException("Invalid DISM driver object.", paramName:=NameOf(dismDriverObject))
End If
Me.dismDriverObject = dismDriverObject.Copy()
Try
Me.Provider = CStr(Me.dismDriverObject.Properties("ProviderName").Value)
Me.ClassName = CStr(Me.dismDriverObject.Properties("ClassName").Value)
Me.ClassDescription = CStr(Me.dismDriverObject.Properties("ClassDescription").Value)
Me.ClassGuid = New Guid(CStr(Me.dismDriverObject.Properties("ClassGuid").Value).Trim("{}".ToCharArray()))
Me.DriverFile = CStr(Me.dismDriverObject.Properties("Driver").Value)
Me.Version = New Version(Me.dismDriverObject.Properties("Version").Value.ToString)
Me.BuildDate = Date.Parse(CStr(Me.dismDriverObject.Properties("Date").Value))
Me.Signature = DirectCast(Me.dismDriverObject.Properties("DriverSignature").Value, DismDriverSignature)
Me.Inbox = CBool(Me.dismDriverObject.Properties("Inbox").Value)
Me.Online = CBool(Me.dismDriverObject.Properties("Online").Value)
Me.BootCritical = CBool(Me.dismDriverObject.Properties("BootCritical").Value)
Me.RestartRequired = CBool(Me.dismDriverObject.Properties("RestartNeeded").Value)
Me.CatalogFile = CStr(Me.dismDriverObject.Properties("CatalogFile").Value)
Me.OriginalFileName = CStr(Me.dismDriverObject.Properties("OriginalFileName").Value)
Catch ex As Exception
Throw
End Try
End Sub
#End Region
#Region " Public Methods "
''' <summary>
''' Returns a String that represents the current <see cref="DismDriverInfo"/> object.
''' </summary>
''' <param name="expandedString">
''' If <see langword="True"/>, returns a single-line string; otherwise, a multi-line string.
''' </param>
''' <returns>
''' A string that represents the current <see cref="DismDriverInfo"/> object.
''' </returns>
<EditorBrowsable(EditorBrowsableState.Always)>
<DebuggerStepThrough>
Public Shadows Function ToString(Optional singleLine As Boolean = True) As String
Dim sb As New StringBuilder(capacity:=512)
If singleLine Then
sb.Append("["c)
sb.Append($"{NameOf(Me.Provider)}:{Me.Provider}, ")
sb.Append($"{NameOf(Me.ClassName)}:{Me.ClassName}, ")
sb.Append($"{NameOf(Me.ClassDescription)}:{Me.ClassDescription}, ")
sb.Append($"{NameOf(Me.ClassGuid)}:{Me.ClassGuid}, ")
sb.Append($"{NameOf(Me.DriverFile)}:{Me.DriverFile}, ")
sb.Append($"{NameOf(Me.Version)}:{Me.Version}, ")
sb.Append($"{NameOf(Me.BuildDate)}:{Me.BuildDate.ToShortDateString()}, ")
sb.Append($"{NameOf(Me.Signature)}:{Me.Signature}, ")
sb.Append($"{NameOf(Me.Inbox)}:{Me.Inbox}, ")
sb.Append($"{NameOf(Me.Online)}:{Me.Online}, ")
sb.Append($"{NameOf(Me.BootCritical)}:{Me.BootCritical}, ")
sb.Append($"{NameOf(Me.RestartRequired)}:{Me.RestartRequired}, ")
sb.Append($"{NameOf(Me.CatalogFile)}:{Me.CatalogFile}, ")
sb.Append($"{NameOf(Me.OriginalFileName)}:{Me.OriginalFileName}, ")
sb.Append($"{NameOf(Me.Directory)}:{Me.Directory.FullName}")
sb.Append("]"c)
Else
sb.AppendLine($"{NameOf(Me.Provider)}: {Me.Provider}")
sb.AppendLine($"{NameOf(Me.ClassName)}: {Me.ClassName}")
sb.AppendLine($"{NameOf(Me.ClassDescription)}: {Me.ClassDescription}")
sb.AppendLine($"{NameOf(Me.ClassGuid)}: {Me.ClassGuid}")
sb.AppendLine($"{NameOf(Me.DriverFile)}: {Me.DriverFile}")
sb.AppendLine($"{NameOf(Me.Version)}: {Me.Version}")
sb.AppendLine($"{NameOf(Me.BuildDate)}: {Me.BuildDate.ToShortDateString()}")
sb.AppendLine($"{NameOf(Me.Signature)}: {Me.Signature}")
sb.AppendLine($"{NameOf(Me.Inbox)}: {Me.Inbox}")
sb.AppendLine($"{NameOf(Me.Online)}: {Me.Online}")
sb.AppendLine($"{NameOf(Me.BootCritical)}: {Me.BootCritical}")
sb.AppendLine($"{NameOf(Me.RestartRequired)}: {Me.RestartRequired}")
sb.AppendLine($"{NameOf(Me.CatalogFile)}: {Me.CatalogFile}")
sb.AppendLine($"{NameOf(Me.OriginalFileName)}: {Me.OriginalFileName}")
sb.AppendLine($"{NameOf(Me.Directory)}: {Me.Directory.FullName}")
End If
Return sb.ToString()
End Function
#End Region
End Class
第二,此功能将用于检索所有已安装的驱动程序:
Public NotInheritable Class DriverUtil
<DebuggerNonUserCode>
Private Sub New()
End Sub
''' <summary>
''' Get infomation about the drivers that are installed
''' on the operating system that is currently running on the local computer.
''' </summary>
''' <param name="flags">
''' Flags combination that determine the function behavior.
''' </param>
''' <returns>
''' A <see cref="ReadOnlyCollection(Of DismDriverInfo)"/> object that represents the information about every driver found.
''' </returns>
<DebuggerStepThrough>
Public Shared Function GetSystemDrivers(flags As GetDriverFlags) As ReadOnlyCollection(Of DismDriverInfo)
If Not flags.HasFlag(GetDriverFlags.Inbox) AndAlso
Not flags.HasFlag(GetDriverFlags.NotInbox) Then
Throw New InvalidEnumArgumentException(NameOf(flags), flags, GetType(GetDriverFlags))
End If
Dim driverInfoList As New List(Of DismDriverInfo)
Dim sessionState As InitialSessionState = InitialSessionState.CreateDefault()
sessionState.ExecutionPolicy = ExecutionPolicy.Unrestricted
sessionState.ImportPSModule("Dism")
Using runspace As Runspace = RunspaceFactory.CreateRunspace(sessionState),
ps As PowerShell = PowerShell.Create(runspace)
Dim hasFlagInbox As Boolean = flags.HasFlag(GetDriverFlags.Inbox)
Dim hasFlagNotInbox As Boolean = flags.HasFlag(GetDriverFlags.NotInbox)
' Save default runspace, if any.
Dim previousDefaultRunSpace As Runspace = Runspace.DefaultRunspace
' Avoids running PowerShell scripts on new threads that has not unrestricted execution policy.
Runspace.DefaultRunspace = runspace
Runspace.DefaultRunspace.Open()
Dim scratchDirectoryPath As String = Path.GetTempPath()
Dim logFilePath As String = Path.Join(Path.GetTempPath(), "Get-WindowsDriver.log")
ps.AddCommand("Get-WindowsDriver")
' Specifies that the action is to be taken on the operating system that is currently running on the local computer.
ps.AddParameter("Online")
' Specifies the full path and file name to log to. If not set, the default is %WINDIR%\Logs\Dism\dism.log.
ps.AddParameter("LogPath", logFilePath)
ps.AddParameter("LogLevel", "2") ' 2 = Errors and warnings
' Specifies a temporary directory that will be used when extracting files for use during servicing.
' The directory must exist locally.
ps.AddParameter("ScratchDirectory", scratchDirectoryPath)
If hasFlagInbox Then
' Get information about default drivers and third-party drivers.
' If you do not specify this parameter, only gets information about third-party drivers.
ps.AddParameter("All")
End If
Dim dismDriverObjects As Collection(Of PSObject)
Try
dismDriverObjects = ps.Invoke()
Catch ex As Exception
Throw
End Try
For Each dismDriverObject As PSObject In dismDriverObjects
Dim driverInfo As New DismDriverInfo(dismDriverObject)
If flags <> GetDriverFlags.Any Then
If (hasFlagInbox AndAlso Not driverInfo.Inbox) OrElse
(hasFlagNotInbox AndAlso driverInfo.Inbox) Then
Continue For
End If
End If
driverInfoList.Add(driverInfo)
Next dismDriverObject
Runspace.DefaultRunspace.Close()
' Restore default runspace, if any.
Runspace.DefaultRunspace = previousDefaultRunSpace
End Using
Return driverInfoList.AsReadOnly()
End Function
End Class
第三个也是最后一个代码示例,演示如何区分第三方驱动程序和默认驱动程序:
' Get all drivers.
Dim allDriversList As ReadOnlyCollection(Of DismDriverInfo) = DriverUtil.GetSystemDrivers(GetDriverFlags.Any)
Debug.WriteLine($"{NameOf(allDriversList)} count: {allDriversList.Count}")
' Get only default (integrated) drivers.
Dim defaultDriversList As ReadOnlyCollection(Of DismDriverInfo) = DriverUtil.GetSystemDrivers(GetDriverFlags.Inbox)
Debug.WriteLine($"{NameOf(defaultDriversList)} count: {defaultDriversList.Count}")
' Get only third-party drivers.
Dim thirdPartyDriversList As ReadOnlyCollection(Of DismDriverInfo) = DriverUtil.GetSystemDrivers(GetDriverFlags.NotInbox)
Debug.WriteLine($"{NameOf(thirdPartyDriversList)} count: {thirdPartyDriversList.Count}")
' Iterate third-party drivers.
For Each driverInfo As DismDriverInfo In thirdPartyDriversList
Debug.WriteLine(driverInfo.ToString(singleLine:=False))
Next driverInfo
输出样本:
ProviderName: Advanced Micro Devices, Inc
ClassName: System
ClassDescription: Dispositivos del sistema
ClassGuid: 4d36e97d-e325-11ce-bfc1-08002be10318
Driver: oem2.inf
Version: 2.2.0.130
Date: 11/03/2020
IsSigned: True
Inbox: False
Online: True
BootCritical: True
RestartNeeded: False
CatalogFile: amdgpio2.cat
OriginalFileName: C:\Windows\System32\DriverStore\FileRepository\amdgpio2.inf_amd64_c72fc3523c1372d0\amdgpio2.inf
Directory: C:\Windows\System32\DriverStore\FileRepository\amdgpio2.inf_amd64_c72fc3523c1372d0
ProviderName: VMware, Inc.
ClassName: Net
ClassDescription: Adaptadores de red
ClassGuid: 4d36e972-e325-11ce-bfc1-08002be10318
Driver: oem16.inf
Version: 14.0.0.5
Date: 09/03/2021
IsSigned: True
Inbox: False
Online: True
BootCritical: False
RestartNeeded: False
CatalogFile: vmnetadapter.cat
OriginalFileName: C:\Windows\System32\DriverStore\FileRepository\netadapter.inf_amd64_8e12d1edcc9e768d\netadapter.inf
Directory: C:\Windows\System32\DriverStore\FileRepository\netadapter.inf_amd64_8e12d1edcc9e768d
...
https://stackoverflow.com/questions/73959146
复制相似问题