Public/OSDCloudTS/Invoke-HPDriverUpdate.ps1
Function Invoke-HPAnalyzer { <# .Name Analyzer.ps1 .Synopsis Analyzer displays possible Softpaq updates available for a platform .DESCRIPTION Analyzer finds 'BIOS', 'Driver', 'Software' Softpaqs that can update the current system .Notes Author: Dan Felman/HP Inc 11/30/2022 - initial release 1.00.01 Changes by Gary: 11/10/2023 - added OSVerOverride parameter - modified output to return only array of updates (or error code if errors) - modified method to get OSVer 12/31/2023 - commented out: (line 347ish) if ( $gh_PnpDriverDate ) { $gh_PnpDriverDate = $gh_PnpDriverDate.ToString("MM-dd-yyyy") } - it was throwing error: Cannot find an overload for "ToString" and the argument count: "1". .Dependencies Requires HP Client Management Script Library HP Business class devices (as supported by HPIA and HP CMSL) Internet access. Analyzer downloads content from Internet .Parameters -a|-All -- [switch] List All Softpaqs and their status -r|-RecommendedSoftware -- [switch] include HP Software HP recommends -s|-ShowHWID -- [switch] list Hardware ID's matched for each driver -d|-DebugOutput -- [switch] add additional info to output -l|-LogFile <file_Path> -- log all output to file_path -c|-CsvLog <file.csv> -- create CSV log file output -n|-NoDots -- [switch] avoid output of '.' while looping (useful when logging output) .Examples # check current device for updates updates Analyzer.ps1 # check current device, with ALL output to file - output updates and up to date Softpaqs Analyzer.ps1 -NoDots -LogFile Out.txt # check current platform, and matching Hardware IDs, include info on ALL Softpaqs Analyzer.ps1 -ShowHWID -All #> [CmdletBinding()] param( # [Parameter(Mandatory = $false)] # [String]$Target, [Parameter(Mandatory = $false)] [switch]$all, [Parameter(Mandatory = $false)] [switch]$RecommendedSoftware, [Parameter(Mandatory = $false)] [switch]$ShowHWID, [Parameter(Mandatory = $false)] [switch]$DebugOutput, [Parameter(Mandatory = $false)] [String]$XmlFile, [Parameter(Mandatory = $false)] [String]$CsvLog, [Parameter(Mandatory = $false)] [String]$LogFile, [Parameter(Mandatory = $false)] [switch]$NoDots, [Parameter(Mandatory = $false)] [switch]$Silent = $true, [Parameter(Mandatory = $false)] [switch]$OSVerOverride, [Parameter(Mandatory = $false)] [switch]$Help ) # param $startTime = (Get-Date).DateTime if (!($Script:LogFile)){ if ($LogFile){ $Script:LogFile = $LogFile } } $Script:RecommendedSWList = @( # these are checked with '-r' option 'HP Notifications', ` 'HP Power Manager', ` 'HP Smart Health', ` 'HP Programmable Key', 'HP Programmable Key (SA)', ` 'HP Auto Lock and Awake', ` 'myHP with HP Presence', ` 'System Default Settings' ) # $Script:RecommendedSWList if ( $Help ) { 'Analyzer displays BIOS/Driver/Software updates available for a platform - requires HP CMSL' 'Runtime options:' '.\Analyzer.exe [-ShowHWID] [-noDots] ...' '.\Analyzer.exe [-S] [-n] ...' ' [-a|-All] --- List All Softpaqs and their status' ' [-r|-RecommendedSoftware] --- Add HP software recommendations to analysis:' ' HP Notifications, HP Power Manager, HP Smart Health, HP Programmable Key' ' HP Auto Lock and Awake, myHP with HP Presence, System Default Settings' ' [-s|-ShowHWID] --- display matching PnP hardware ID' ' [-l|-LogFile <File>] --- Log all output to file instead of console' ' -l out.txt log output to out.txt' ' -l out.csv log output to out.csv (formatted) AND to out.txt' ' [-c|-CsvLog file[.csv]] --- log output to out.csv (formatted)' ' [-n|-noDots] --- avoid displaying dot/Softpaq to console (- )useful when using -l)' ' [-x|-XmlFile <File.xml>]] --- Reference file argument - avoids Internet access for analysis' return 0 } # if ( $Help ) ##################################################################################### # Set up initial variables and checks ##################################################################################### if ( $CsvLog -and ([System.IO.Path]::GetExtension($CsvLog) -notlike '.csv') ) { $CsvLog = $CsvLog+'.csv' } # use CMSL to find what is the device Try { $ThisPlatformID = Get-HPDeviceProductID $ThisPlatformName = Get-HPDeviceModel } Catch { Write-Warning 'HP CMSL is not available on this device, or device not supported' return 1 } ##################################################################################### # if $OS not passed as argument, used installed OS $WinOS = Get-CimInstance win32_operatingsystem # $OS = 'win'+$WinOS.version.split('.')[0] if ( $WinOS.BuildNumber -lt 22000 ) { $OS = 'win10' } else { $OS = 'win11' } #Replaced Dan's Switch Method with grabbing it from the Regsitry $OSVer = Get-ItemPropertyValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'DisplayVersion' if ($OSVerOverride){ $MaxOSSupported = ((Get-HPDeviceDetails -oslist).OperatingSystem | Where-Object {$_ -notmatch "LTSB"} | Select-Object -Unique| measure -Maximum).Maximum if ($MaxOSSupported -Match "11"){$MaxOS = "Win11"} else {$MaxOS = "Win10"} $MaxBuild = ((Get-HPDeviceDetails -oslist | Where-Object {$_.OperatingSystem -eq "$MaxOSSupported"}).OperatingSystemRelease | measure -Maximum).Maximum #Write-Host " Max Build Supported for this Device: $MaxBuild" #Write-Host " Max OS: $MaxOS" $OSVer = $MaxBuild $OS = $MaxOS $script:OSOVerOverRideComment = "Overriding OS and/or OSVer with: $OS & $OSVer" } <# Dan's Method switch -Wildcard ( $WinOS.version ) { '*18363' { $OSVer = '1909' } '*19041' { $OSVer = '2004' } '*19042' { $OSVer = '2009' } '*19043' { $OSVer = '21H1' } '*19044' { $OSVer = '21H2' } '*19045' { $OSVer = '22H2' } '*22000' { $OSVer = '21H2' } '*22621' { $OSVer = '22H2' } '*25262' { $OSVer = '22H2' } # insider preview '*25267' { $OSVer = '22H2' } # insider preview '*25276' { $OSVer = '22H2' } # insider preview '*25290' { $OSVer = '22H2' } # insider preview default { "OS Version $($OSVer.version) not supported" ; return -1 } } # switch -Wildcard ( (Get-WmiObject win32_operatingsystem).version ) #> ##################################################################################### $Script:xmlRefFileContent = $null $CacheDir = (Convert-Path (Get-Location)) # get current location of script if ( $XmlFile ) { if ( Test-Path $XmlFile ) { Try { $Error.Clear() $SoftpaqList = Get-SoftpaqList -platform $ThisPlatformID -os $OS -OsVer $OSVer -ReferenceUrl $CacheDir -ErrorAction Stop } Catch { $error[0].exception # $error[0].exception.gettype().fullname return 3 } } else { 'File not found' return 3 } # else if ( Test-Path $XmlFile ) } else { Try { $Error.Clear() $Script:SoftpaqList = Get-SoftpaqList -platform $ThisPlatformID -os $OS -OsVer $OSVer -CacheDir $CacheDir -ErrorAction Stop } Catch { $error[0].exception # $error[0].exception.gettype().fullname 'Remove "cache" folder and try again' if ( $OSVer -eq '22H2' ) { 'NOTE: CMSL version >= 1.6.8 is required to support Windows 22H2' } return -2 } # find the downloaded reference file (as expanded from the cab file) $XmlFile = Get-Childitem -Path $CacheDir'\cache' -Include "*.xml" -Recurse -File | where { ($_.Directory -match '.dir') -and ` ($_.Name -match $ThisPlatformID) -and ` ($_.Name -match $OS.Substring(3)) -and ` ($_.Name -match $OSVer) } } # else if ( $XmlFile ) $Script:xmlContent = [xml](Get-Content -Path $XmlFile) $Script:XMLRefFileDevices = $Script:xmlContent.SelectNodes("ImagePal/Devices/Device") # error codes for color coding, etc. $TypeError = -1 ; $TypeNorm = 1 ; $TypeWarn = 2 ; $TypeDebug = 4 ; $TypeSuccess = 5 ;$TypeNoNewline = 10 ##################################################################################### # End of initialization ##################################################################################### function TraceLog { [CmdletBinding()] param( [Parameter(Mandatory = $false)] $Message, [Parameter(Mandatory = $false)] [int]$Type ) if ( $null -eq $Type ) { $Type = $TypeNorm } #$LogMessage = "<$Message><time=`"$Time`" date=`"$Date`" type=`"$Type`">" if ( $Script:LogFile ) { $Message | Out-File -Append -Encoding UTF8 -FilePath $Script:LogFile.replace('.csv','.log') } else { if ($Silent -ne $true){ if ( $Type -eq $TypeNoNewline ) { Write-host $Message -NoNewline } else { $Message | Out-Host } } } # else if ( $Script:LogFile ) } # function TraceLog #Write-Host "LogFile: $Script:LogFile" #Write-Host "LogFile: $LogFile" TraceLog -Message "Analyzer: 2.01.02 -- $($startTime)" TraceLog -Message "-- Working Reference File: '$XmlFile'" <###################################################################################### Function Compare_Version This function compares 2 driver version strings (4 digits separated by '.') Returns 'True' if first parm is higher than second parm parm: $pInstalled Installed driver version $pToMatch Driver version to compare against (latest) return: True (Update needed) if current version is newer than what's installed #>##################################################################################### Function Compare_Version { [CmdletBinding()] param( $pInstalled, $pToMatch ) if ( -not $pInstalled ) { return $true } # handle case: '1.1.28.1 A 7' (like in HP Notifications) if ( $pInstalled.contains(' ') ) { $pInstalled = $pInstalled.split(' ')[0] } if ( $pToMatch.contains(' ') ) { $pToMatch = $pToMatch.split(' ')[0] } $a =$pInstalled.Split(".") $b =$pToMatch.Split(".") $cv_UpdateNeeded = $false # assume update is not needed if ( [int32]$a[0] -lt [int32]$b[0] ) { $cv_UpdateNeeded = $true } else { if ( [int32]$a[0] -gt [int32]$b[0] ) { $cv_UpdateNeeded = $false } else { # first digits are the same if ( [int32]$a[1] -lt [int32]$b[1] ) { $cv_UpdateNeeded = $true } else { if ( [int32]$a[1] -gt [int32]$b[1] ) { $cv_UpdateNeeded = $false } else { # second digits are the same if ( [int32]$a[2] -lt [int32]$b[2] ) { $cv_UpdateNeeded = $true } else { if ( [int32]$a[2] -gt [int32]$b[2] ) { $cv_UpdateNeeded = $false } else { # third digits are the same if ( [int32]$a[3] -lt [int32]$b[3] ) { $cv_UpdateNeeded = $true } else { if ( [int32]$a[3] -ge [int32]$b[3] ) { $cv_UpdateNeeded = $false } } # else if ( [int]$a[3] -lt [int]$b[3] ) } } # else if ( [int]$a[2] -lt [int]$b[2] ) } } # else if ( [int]$a[1] -lt [int]$b[1] ) } } # else if ( [int]$a[0] -lt [int]$b[0] ) return $cv_UpdateNeeded } # Function Compare_Version <###################################################################################### Function Decode_VersionHexString This function returns the int version of the hex string passed as arg the argument string may contain other non-hex characters (which are removed) parm: $pHexLine string containing 4 digit hex string separated by '.' return: 4 separate int digits (as strings) #>##################################################################################### Function Decode_VersionHexString { [CmdletBinding()] param( $pHexLine ) $dv_ReturnValue = $null if ( $pHexLine.contains('0x') ) { foreach ( $i in $pHexLine.split(',') ) { ## create the driver string if ( $i.contains('0x') ) { #Write-Host "$i" if ($i.contains('\')){ $i = $i.split('\')[0] } $dv_ReturnValue += ([int32]$i).Tostring() ; $dv_ReturnValue += '.' } } # foreach ( $i in $pHexLine.split(',') $dv_ReturnValue = $dv_ReturnValue -replace ".$" # remove last added '.' from string } # if ( $pHexLine.contains('0x') ) Return $dv_ReturnValue } # Function Decode_VersionHexString <###################################################################################### Function Get_HardwareID This function checks for a Softpaq's supported Hardware ID and tries to match one in the current system of installed drivers parm: $pCVAMetadata contents of CVA's file $pInstalledDrivers list of installed PnP drivers return: matching Hardware ID or $null, and the PnP driver version, PnP driver date #>##################################################################################### Function Get_HardwareID { [CmdletBinding()] param( $pCVAMetadata, $pInstalledDrivers ) if ( $DebugOutput ) { TraceLog -Message ' > Get_HardwareID() Checking PnP Hardware for match' } $gh_MatchedHardwareID = $null $gh_PnPDriverVersion = $null $gh_PnpDriverDate = $null $gh_RefFileVersion = $null $gh_DriverProvider = $null # CVA file example: # [Devices] # HDAUDIO\FUNC_01&VEN_14F1&DEV_50F4="Conexant ISST Audio" # PCI\VEN_8086&DEV_9D70="Intel(R) Smart Sound Technology (Intel(R) SST) Audio Controller" # PCI\VEN_8086&DEV_A170="Intel(R) Smart Sound Technology (Intel(R) SST) Audio Controller" # check the list of installed PnP devices for a matching entry in the CVA [Devices] list foreach ( $gh_iDriver in $pInstalledDrivers ) { if ( $gh_iDriver.DeviceID ) { # assume this entry has a h/w ID component (could a s/w entry, print, etc.) foreach ($gh_iDevIDEntry in $pCVAMetadata.Devices.Keys) { # $pCVAMetadata.Devices.Keys: entry up to '=' if ( $gh_iDevIDEntry -like '_body' ) { continue } # next remove '*' from entry (example: HID\*HPQ6001="HP Wireless Button Driver") #$gh_DevToMatch = ($gh_iDevIDEntry.split('\')[1]).split('=')[0].replace('*','') # ex. 'VEN_8086&DEV_51FC' $gh_DevToMatch = $gh_iDevIDEntry.split('=')[0] if ( $gh_iDriver.DeviceID -match ($gh_DevToMatch.replace('\','\\')) ) { $gh_MatchedHardwareID = $gh_DevToMatch $gh_PnPDriverVersion = $gh_iDriver.DriverVersion $gh_PnpDriverDate = $gh_iDriver.DriverDate $gh_DriverProvider = $gh_iDriver.DriverProviderName #if ( $gh_PnpDriverDate ) { $gh_PnpDriverDate = $gh_PnpDriverDate.ToString("MM-dd-yyyy") } if ( $DebugOutput ) { TraceLog -Message " ... Matched CVA Device ID: $($gh_DevToMatch)" TraceLog -Message " ... Matched HWID : $($gh_MatchedHardwareID)" TraceLog -Message " ... Matched HWID Driver Version : $($gh_PnPDriverVersion)" TraceLog -Message " ... Matched HWID Driver Date : $($gh_PnpDriverDate)" TraceLog -Message " ... Matched HWID Provider Name: $($gh_DriverProvider)" } # if ( $DebugOutput ) break } # $gh_iDriver.DeviceID -match $gh_DevToMatch if ( $gh_MatchedHardwareID ) { break } } # foreach ($gh_iDevIDEntry in $pCVAMetadata.Devices.Keys) } # if ( $gh_iDriver.DeviceID ) } # foreach ( $gh_iDriver in $pInstalledDrivers ) # check 'reference file' for this entry, and get the driver version from it if ( $gh_MatchedHardwareID ) { if ( $gh_MatchedHardwareID.contains('&') ) { $gh_devEntryToFind = $gh_MatchedHardwareID.split('&')[1]# ACPI\VEN_HPQ&DEV_6007="HP Mobile Data Protection Sensor" } else { $gh_devEntryToFind = $gh_MatchedHardwareID # ACPI\HPQ6007="HP Mobile Data Protection Sensor" } # check the Reference File for devices that match foreach ( $gh_iDevEntry in $Script:XMLRefFileDevices.Device ) { if ( $gh_iDevEntry.DeviceID -match ($gh_devEntryToFind.replace('\','\\')) ) { $gh_RefFileVersion = $gh_iDevEntry.DriverVersion # return the Reference File driver version break } # if ( $gh_iDevEntry.DeviceID -match $gh_devEntryToFind } # foreach ( $gh_iDevEntry in $Script:XMLRefFileDevices.Device ) } # if ( $gh_MatchedHardwareID ) # if the Refernence File <Devices> section does not have this entry, # ... check in <Solutions> if ( $null -eq $gh_RefFileVersion ) { foreach ( $gh_iSolution in $Script:XMLRefFileSolutions.UpdateInfo ) { $gh_SolutionID = $gh_iSolution.ID $gh_SolutionVersion = $gh_iSolution.Version if ( $gh_SolutionID -like $pCVAMetadata.Softpaq.SoftpaqNumber ) { $gh_RefFileVersion = $gh_iSolution.Version break } } # foreach ( $gh_iSolution in $Script:XMLRefFileSolutions.UpdateInfo ) } # if ( $null -eq $gh_RefFileVersion ) if ( $DebugOutput ) { if ( $gh_MatchedHardwareID ) { TraceLog -Message " < Get_HardwareID()[0] PnP matched - HWID: $($gh_MatchedHardwareID)" TraceLog -Message " ... [1] HWID Driver version: $($gh_PnPDriverVersion)" TraceLog -Message " ... [2] HWID Driver Date: $($gh_PnpDriverDate)" TraceLog -Message " ... [3] Reference File Version: $($gh_RefFileVersion)" } else { TraceLog -Message ' < Get_HardwareID() PnP driver NOT matched' } # else if ( $gh_MatchedHardwareID ) } # if ( $DebugOutput ) return $gh_MatchedHardwareID, $gh_PnPDriverVersion, $gh_PnpDriverDate, $gh_RefFileVersion } # Function Get_HardwareID <###################################################################################### Function Get_DriverFileVersion This function returns the version string from a CVA file's [DetailFileInformation] section from the driver filr, matching the OS version being analyzed or the generic 'WT64' Each [DetailFileInformation] entry has the DriverName=... syntax ptf.dll=<WINSYSDIR>\DriverStore\FileRepository\dptf_cpu.inf_amd64_897ea327b3fe52f7\,0x0008,0x0007,0x29CC,0x57E6,WT64_2004 parm: $pCVAContent contents of CVA's file $pOSToMatch OS to match $pOSVerToMatch OS Version to match return: $gd_DetailDriverFileVersion # driver version from CVA file $gd_DriverName # name of driver from CVA file #>##################################################################################### Function Get_DriverFileVersion { [CmdletBinding()] param( $pCVAMetadata, $pOSToMatch , $pOSVerToMatch ) if ( $DebugOutput ) { TraceLog -Message ' > Get_DriverFileVersion() Checking Driver File for match' } $gd_SoftpaqID = $pCVAMetadata.Softpaq.SoftpaqNumber $gd_CVADetailFileInfo = $pCVAMetadata.DetailFileInformation $gd_DetailDriverFileVersion = $null $gd_CVADetailVersion = $null $gd_DriverName = $null # search each key (driver) and see what driver versions it returns, match OS and Version $gd_Drivers = $gd_CVADetailFileInfo.Keys foreach ( $gd_iDriver in $gd_Drivers ) { if ( $gd_iDriver -like '_body' ) { continue } if ( $null -ne $gd_DetailDriverFileVersion ) { break } # let's search for driver version in an entry foreach ( $gd_iEntry in $gd_CVADetailFileInfo.Item($gd_iDriver) ) { # let's match the OS Version 1st $gd_iEntryOSVer = $gd_iEntry.Substring($gd_iEntry.Length-4) if ( ($gd_iEntryOSVer -match $pOSVerToMatch) -and ($gd_iEntry -match $pOSToMatch) ) { #Write-Output "$gd_iEntry" $gd_CVADetailVersion = Decode_VersionHexString $gd_iEntry -ErrorAction SilentlyContinue $gd_DriverName = $gd_iDriver $gd_DriverPath = $gd_iEntry.split(',')[0] # Exception: make sure the path has a '\' at the end (not always the case) if ( $gd_DriverPath -notmatch '\\$' ) { $gd_DriverPath=$gd_DriverPath+'\' } $gd_PathToken = $gd_DriverPath.split('\')[0] # get CVA coded path token, ex. <WINSYSDIR>, <PROGRAMFILESDIR>, etc. switch ( $gd_PathToken ) { # Following from CVA documentation about paths '<DRIVERS>' { $gd_DriverPath=$gd_DriverPath.replace($gd_PathToken,"C:\Windows\System32\drivers") } '<PROGRAMFILESDIR>' { $gd_DriverPath=$gd_DriverPath.replace($gd_PathToken,"C:\Program Files") } '<PROGRAMFILESDIRX86>' { $gd_DriverPath=$gd_DriverPath.replace($gd_PathToken,"C:\Program Files (x86)") } '<WINDIR>' { $gd_DriverPath=$gd_DriverPath.replace($gd_PathToken,"C:\Windows") } '<WINDISK>' { $l_SysDrive = (Get-CimInstance -ClassName CIM_OperatingSystem).SystemDrive $gd_DriverPath=$gd_DriverPath.replace($gd_PathToken,$l_SysDrive) } '<WINSYSDIR>' { $gd_DriverPath=$gd_DriverPath.replace($gd_PathToken,"C:\Windows\System32") } '<WINSYSDIRX86>' { $gd_DriverPath=$gd_DriverPath.replace($gd_PathToken,"C:\WINDOWS\SYSWOW64") } '<WINSYSDISK>' { $gd_DriverPath=$gd_DriverPath.replace($gd_PathToken,($env:windir).split('\')[0]) } default { '?UNKNOWN?' | out-host } } # switch ( $gd_PathToken ) $gd_DriverFullPath = $gd_DriverPath+$gd_DriverName ##################################################################################### # check if driver is installed (meaning the file exists) and obtain file version ##################################################################################### if ( $DebugOutput ) { TraceLog -Message " Get_DriverFileVersion(): CVA file Driver Path: $($gd_DriverFullPath)" } if ( Test-Path $gd_DriverFullPath -EA continue ) { $gd_DetailDriverFileVersion = (get-itemproperty $gd_DriverFullPath).versioninfo.FileVersion # Exception: fix returns '8, 5, 3459, 0' instead of '8.5.3459.0' (sp91426 driver dll file) $gd_DetailDriverFileVersion = $gd_DetailDriverFileVersion.replace(', ','.') if ( -not $gd_DetailDriverFileVersion ) { $gd_DetailDriverFileVersion = (get-itemproperty $gd_DriverFullPath).versioninfo.productversion } } else { if ( $DebugOutput ) { TraceLog -Message " Get_DriverFileVersion(): $($gd_SoftpaqID) -- CVA Driver Path NOT FOUND: $($gd_DriverFullPath)" } } } # if ( ... ) } # foreach ($v in $f_values) } # foreach ($gd_iDriver in $gd_CVADetailFileInfo.Keys) if ( $DebugOutput ) { TraceLog -Message " < Get_DriverFileVersion() [0] Driver File Version: $($gd_DetailDriverFileVersion)" TraceLog -Message " < ... [1] Driver File Name: $($gd_DriverName)" TraceLog -Message " < ... [2] Detail File Version: $($gd_CVADetailVersion)" } # if ( $DebugOutput ) return $gd_DetailDriverFileVersion, $gd_DriverName, $gd_CVADetailVersion } # Function Get_DriverFileVersion <###################################################################################### Function Get_InstalledAppx Find out if the Softpaq appx has an installed version in system parm: $pAppxFullName the Appx we are looking for $pInstalledAppx name of appx in system to check for match return: $iAppx the reg entry for the matching appx #>##################################################################################### Function Get_InstalledAppx { [CmdletBinding()] param( $pAppxFullName, $pInstalledAppx ) $gi_AppxInstalledName = $null $gi_AppxInstalledVersion = $null foreach ( $iAppx in $pInstalledAppx ) { if ( $iAppx.Name -match $pAppxFullName ) { # get the installed app version from the name string $gi_AppxInstalledName = $iAppx.Name break } # if ( $iAppx.Name -match $gu_AppxFullName ) $iAppx = $null } # foreach ( $iAppx in $pInstalledAppx ) return $iAppx } # Function Get_InstalledAppx <###################################################################################### Function Get_UWPInfo This functions determines if the Softpaq has a UWP requirement and if it is installed Parms: $pRefFileUWPApps: content of all UWP apps section from reference file $pSoftpaqID: Softpaq ID $pInstalledAppx: registry list of UWP/appx installed in system Returns: the Softpaq UWP name and version, and (if) installed the UWP version [0] UWP name - from reference file (or $null) [1] UWP version - from reference file (or $null) [2] UWP version - from installed UWP (or $null) [3] UWP Name - from installed UWP (or $null) #>##################################################################################### Function Get_UWPInfo { [CmdletBinding()] param( $pCVAMetadata, $pInstalledAppx ) $gu_SoftpaqID = $pCVAMetadata.Softpaq.SoftpaqNumber if ( $DebugOutput ) { TraceLog -Message " > Get_UWPInfo(): $($gu_SoftpaqID) - Checking for UWP appx" } $gu_CVAUWPName = $null $gu_CVAUWPVersion = $null $gu_AppxInstalledVersion = $null if ( $pCVAMetadata.Private.MS_Store_App -eq 1 ) { # find the UWP package info under $gu_UWPPackageList = $pCVAMetadata.'Store Package Info' foreach ( $iPkg in $gu_UWPPackageList.Keys ) { if ($iPkg -notlike '_body' ) { # obtain name of Appx from full name - e.g. 'HPPenSettings' from WacomTechnologyCorp.HPPenSettings_7.7.64.0_neutral__ss941bf8mfs8a # split full appx name into a hash table $gu_UWPPackageHash = $iPkg.split('_') # package: <Name>_<Version>_<Architect>_<ResourceId>_<PublisherId> # NVIDIAControlPanel_8.1.962.0_x64__56jybvy8sckqj $gu_CVAUWPName = $gu_UWPPackageHash[0] # NVIDIAControlPanel $gu_CVAUWPVersion = $gu_UWPPackageHash[1] # 8.1.962.0 $gu_AppxArchitecture = $gu_UWPPackageHash[2] # x64 break } } # foreach ( $iPkg in $gu_UWPPackageList.Keys ) # now let's see if the Softpaq UWP is an installed appx in the system $gu_InstalledAppx = Get_InstalledAppx $gu_CVAUWPName $pInstalledAppx if ( $null -eq $gu_InstalledAppx ) { $gu_AppxInstalledVersion = $null } else { $gu_AppxInstalledVersion = $gu_InstalledAppx.version } } # if ( $pCVAMetadata.Private.MS_Store_App -eq 1 ) if ( $DebugOutput ) { if ( $gu_CVAUWPVersion ) { TraceLog -Message " < Get_UWPInfo() Softpaq: $($gu_SoftpaqID)" TraceLog -Message " ... [0] UWP App Name: $($gu_CVAUWPName)" TraceLog -Message " ... [1] UWP Version: $($gu_CVAUWPVersion)" TraceLog -Message " ... [2] UWP Installed Version: $($gu_AppxInstalledVersion)" } else { TraceLog -Message " < Get_UWPInfo() Softpaq: $($gu_SoftpaqID) - NO UWP" } } # if ( $DebugOutput ) return $gu_CVAUWPName, $gu_CVAUWPVersion, $gu_AppxInstalledVersion } # Function Get_UWPInfo <###################################################################################### Function Find_Driver This functions attempts to match a Softpaq against an installed driver It parses the CVA file [Devices] HW PnP list against this PnP Hardware IDs to find a match, and then checks for the associated driver version info against the CVA version Parms: $pSoftpaq: Softpaq node from Get-SoftpaqList $pCVAMetadata: contents of Softpaq's CVA file $pInstalledDrivers: list of installed Drivers in the OS (those w/driver versions) (obtained with 'Get-CimInstance win32_PnpSignedDriver') Returns: 5 values [0] Matching H/W ID - $null if not found [1] Installed driver version (PNP) - $null if not found [2] installed driver date [3] Reference driver version [4] Status #>##################################################################################### Function Find_Driver { [CmdletBinding()] param( $pSoftpaq, $pCVAMetadata, $pInstalledDrivers ) if ( $DebugOutput ) { TraceLog -Message ' > Find_Driver() Checking driver' } $fd_MatchedHardwareID = $null $fd_Installed_DriverVersion = $null if ( $Script:OS -eq 'win10') { $Script:OS = 'WT64' } if ( $Script:OS -eq 'win11') { $Script:OS = 'W11' } ############################################################################## # get insgtalled driver version matching the CVA driver info in [DetailFileInformation] # Get_DriverFileVersion(): $gd_DetailDriverFileVersion, $gd_DriverName, $gd_CVADetailVersion $fd_Status = -1 $fd_CVADriverInfo = Get_DriverFileVersion $pCVAMetadata $Script:OS $Script:OSVer $fd_CVADriverFileVersion = $fd_CVADriverInfo[0] # this driver is in the system $fd_CVADriverFileName = $fd_CVADriverInfo[1] # driver name $fd_CVADriverDetailVersion = $fd_CVADriverInfo[2] # driver version from CVA [DetailFileInformation] if ( $fd_CVADriverFileVersion ) { $fd_CVADriverFilecompare = Compare_Version $fd_CVADriverFileVersion $fd_CVADriverDetailVersion if ( $fd_CVADriverFilecompare ) { $fd_Status = 1 } else { $fd_Status = 0 } } ############################################################################## ############################################################################## # Check installed driver matching the Softpaq's driver hardware ID # see if the driver matches an install PnP device # Get_HardwareID(): $gh_MatchedHardwareID, $gh_PnPDriverVersion, $gh_PnpDriverDate, $gh_RefFileVersion ############################################################################## $fd_HardwareCheck = Get_HardwareID $pCVAMetadata $pInstalledDrivers $fd_MatchedHardwareID = $fd_HardwareCheck[0] # [0]=PnP ID matched $fd_PnPDriverVersion = $fd_HardwareCheck[1] # [1]=PnP DriverVersion $fd_PnPDriverDate = $fd_HardwareCheck[2] # [2]=PnP DriverDate $fd_RefFileDriverVersion = $fd_HardwareCheck[3] # [3]=Driver version from Reference file ($null if not in) if ( $fd_MatchedHardwareID ) { $fd_compareToReferenceFileVersion = Compare_Version $fd_PnPDriverVersion $fd_RefFileDriverVersion if ( $fd_compareToReferenceFileVersion ) { $fd_Status = 1 } else { $fd_Status = 0 } } if ( $DebugOutput ) { TraceLog -Message " < Find_Driver() [0] SysHardwareID: $($fd_MatchedHardwareID)" TraceLog -Message " < ... [1] Installed DriverVersion: $($fd_PnPDriverVersion)" TraceLog -Message " < ... [2] Installed DriverDate: $($fd_PnPDriverDate)" TraceLog -Message " < ... [3] Ref File DriverVersion: $($fd_RefFileDriverVersion), $($fd_CVADriverDetailVersion)" TraceLog -Message " < ... [4] Status: $($fd_Status)" } # if ( $DebugOutput ) return $fd_MatchedHardwareID, $fd_PnPDriverVersion, $fd_PnPDriverDate, $fd_RefFileDriverVersion, $fd_Status } # Function Find_Driver <###################################################################################### Function Find_Software ... Parm: $pSoftpaq: Softpaq node entry to match in device, $pSpqMetadata: contents of Softpaq's CVA file $pInstalledSoftware: List of Uninstall registry app entries Return: app found or $null #>##################################################################################### Function Find_Software { [CmdletBinding()] param( $pSoftpaq, $pCVAMetadata, $pInstalledSoftware, $pInstalledWOWApps ) if ( $DebugOutput ) { TraceLog -Message " > Find_Software() - Checking Software" } $fs_AppName = $null $fs_AppVersion = $null $fs_AppDate = $null $fs_NameToMatch = $pSoftpaq.name # handle exceptions in names between installed app and CVA Title name if ( $pSoftpaq.name -match 'BIOS Config Utility' ) { $fs_NameToMatch = 'HP BIOS Configuration Utility' } if ( $pSoftpaq.name -match 'Cloud Recovery' ) { $fs_NameToMatch = 'HP Cloud Recovery' } # search Uninstall entries for matching Software, list obtained with 'Get-ItemProperty' foreach ( $iInst in $pInstalledSoftware ) { if ( $iInst.DisplayName -match $fs_NameToMatch ) { $fs_AppVersion = $iInst.DisplayVersion $fs_AppDate = $iInst.InstallDate $fs_AppName = $iInst.DisplayName break } } # foreach ( $iInst in $pInstalledSoftware ) if ( $null -eq $fs_AppVersion ) { # search WoW Uninstall entries for matching Software, list obtained with 'Get-ItemProperty' foreach ( $iInst in $pInstalledWOWApps ) { if ( $iInst.DisplayName -match $fs_NameToMatch ) { $fs_AppVersion = $iInst.DisplayVersion $fs_AppDate = $iInst.InstallDate $fs_AppName = $iInst.DisplayName break } } # foreach ( $iInst in $pInstalledSoftware ) } # if ( $null -eq $fs_AppFound ) if ( $DebugOutput ) { if ( $fs_AppFound ) { TraceLog -Message " < Find_Software() - Installed Version: $($fs_AppFound.DisplayVersion)" } else { TraceLog -Message " < Find_Software() - Software from $($pSoftpaq.id) NOT installed" } } # if ( $DebugOutput ) return $fs_AppVersion, $fs_AppDate, $fs_AppName } # Function Find_Software <###################################################################################### Function Analyze Searches the current system for a match for the Softpaq in question Parm: $pSoftpaq: Softpaq node entry (from Get-SoftpaqList) to match in device $pSpqMetadata: contents of Softpaq's CVA file $pDriversList: List of PnP installed drivers, OR Captured Config Devices list (XML format) Return: a PS Hash Table entry containing information about found component #>##################################################################################### Function Analyze { [CmdletBinding()] param( $pSoftpaq, $pSpqMetadata, $pDriversList, $pApps, $pWOWApps, $pInstalledAppxApps, $pRefFileUWPs ) $SoftpaqHashEntry = @{} $a_AnalyzeType = $pDriversList.GetType().BaseType.Name # returns 'Array' or 'XmlNode' (e.g. Target File) if ( $DebugOutput ) { TraceLog -Message " Analyze() $($pSoftpaq.id): $($pSoftpaq.Category)" } # setup initial hash entry with certain default data from the Softpaq $SoftpaqHashEntry = @{ SoftpaqID = $pSoftpaq.id ; ` SoftpaqName = $pSoftpaq.name ; ` SoftpaqVersion = $pSoftpaq.Version ; ` SoftpaqDate = $pSoftpaq.ReleaseDate ; ` ReleaseType = $pSoftpaq.ReleaseType ; ` URL = $pSoftpaq.url ; ` } if ( $pSoftpaq.Category -match 'bios' ) { if ( $a_AnalyzeType -eq 'Array') { $a_InstalledBIOS = Get-HPBIOSSettingValue 'System BIOS Version' # ex. 'Q70 Ver. 01.19.20 03/21/2022' $a_InstalledBIOS = $a_InstalledBIOS.split(' ')[2] $a_InstalledBIOSDate = $a_InstalledBIOS.substring($a_InstalledBIOS.lastIndexOf(' ')+1) } else { #'XMLNode' $a_TargetSystem = $pDriversList.SelectNodes("ImagePal/SystemInfo/System") $a_InstalledBIOS = $a_TargetSystem.BiosVersion2.split(' ')[2] # BiosVersion2: "Q70 Ver. 01.19.20" } $a_SoftpaqBIOS = $pSoftpaq.Version if ($a_SoftpaqBIOS -match "A"){$a_SoftpaqBIOS = ($a_SoftpaqBIOS.Split("A")[0]).replace(" ","")} if ( $a_InstalledBIOS -match "^0" -and ($a_SoftpaqBIOS -notmatch "^0") ) { $a_SoftpaqBIOS = '0'+$a_SoftpaqBIOS } if ( $a_InstalledBIOS -lt $a_SoftpaqBIOS ) { $a_Status = '1' # "-- BIOS UPDATE AVAILABLE" } else { $a_Status = '0' # "-- BIOS UP TO DATE" } # else if ( $a_InstalledBIOS -lt $a_SoftpaqBIOS ) $SoftpaqHashEntry.Category = 'BIOS' ; ` $SoftpaqHashEntry.InstallVersion = $a_InstalledBIOS ; ` $SoftpaqHashEntry.InstallDate = $a_InstalledBIOSDate ; ` $SoftpaqHashEntry.Status = $a_Status if ( $DebugOutput ) { TraceLog -Message " Analyze() BIOS Check Status: $($a_Status)" } } if ( $pSoftpaq.Category -match 'driver' ) { #if ( $pSoftpaq.name -match 'firmware' ) { continue } if ( $a_AnalyzeType -eq 'Array') { $a_DvrReturnArray = Find_Driver $pSoftpaq $pSpqMetadata $pDriversList } else { #'XMLNode' $a_TargetDeviceList = $pDriversList.SelectNodes("ImagePal/Devices/Device") $a_DvrReturnArray = Find_Driver $pSoftpaq $pSpqMetadata $a_TargetDeviceList } # Find_Driver(): $fd_MatchedHardwareID, $fd_PnPDriverVersion, $fd_PnPDriverDate, $fd_RefFileDriverVersion, $fd_Status if ( $a_DvrReturnArray[0] ) { # Hardware ID matched, e.g. not $null $SubCategory = $pSoftpaq.Category $SubCategoryShort = $SubCategory.Replace(" ","").Split("-") | Select-Object -Last 1 $SoftpaqHashEntry.SoftpaqVersion = $a_DvrReturnArray[3] ; ` $SoftpaqHashEntry.Category = 'Driver' ; ` $SoftpaqHashEntry.Vendor = $pSoftpaq.Vendor ; ` $SoftpaqHashEntry.SubCategory = $SubCategoryShort ; ` $SoftpaqHashEntry.InstallVersion = $a_DvrReturnArray[1] ; ` $SoftpaqHashEntry.InstallDate = $a_DvrReturnArray[2] ; ` $SoftpaqHashEntry.CVAHWID = $a_DvrReturnArray[0] ; ` $SoftpaqHashEntry.Status = $a_DvrReturnArray[4] ; ` $SoftpaqHashEntry.UWP = $pSoftpaq.UWP ; ` $SoftpaqHashEntry.UWPName = $null ; ` $SoftpaqHashEntry.UWPVersion = $null ; ` $SoftpaqHashEntry.UWPInstallVersion = $null ; ` $SoftpaqHashEntry.CVAStoreApp = $null ; ` # $pSpqMetadata.Private.MS_Store_App # 0 or 1 $SoftpaqHashEntry.CVAStorePackageInfo = $null ; ` # is there info in CVA's 'Store Package Info' section? $SoftpaqHashEntry.UWPStatus = -1 # default to 'NOT Installed' if ( $SoftpaqHashEntry.Status -ge 0 ) { # 0=UP-To-Date, 1=Update, -1=Not Installed if ( $null -eq $SoftpaqHashEntry.InstallVersion ) { # There is a driver available, Hardware exists, but no driver was installed $SoftpaqHashEntry.InstallVersion = 'MISSING' } # check on UWP/appx apps in driver # Get_UWPInfo(): $gu_CVAUWPName, $gu_CVAUWPVersion, $gu_AppxInstalledVersion $a_UWPInfo = Get_UWPInfo $pSpqMetadata $pInstalledAppxApps if ( $a_UWPInfo[1] ) { # we found a Softpaq with a UWP appx listed in the CVA file $SoftpaqHashEntry.UWPName = $a_UWPInfo[0].split('.')[1] $SoftpaqHashEntry.UWPVersion = $a_UWPInfo[1] $SoftpaqHashEntry.UWPInstallVersion = $a_UWPInfo[2] $SoftpaqHashEntry.CVAStorePackageInfo = 1 if ( $SoftpaqHashEntry.UWPInstallVersion ) { $SoftpaqHashEntry.UWPStatus = 0 # -- UWP UP TO DATE $a_UWPNeesUpdate = Compare_Version $SoftpaqHashEntry.UWPInstallVersion $SoftpaqHashEntry.UWPVersion if ( $a_UWPNeesUpdate) { $SoftpaqHashEntry.UWPStatus = 1 # -- UWP UPDATE AVAILABLE } } else { $SoftpaqHashEntry.UWPStatus = -1 # -- UWP NOT INSTALLED } # else if ( $SoftpaqHashEntry.UWPInstallVersion ) if ( $DebugOutput ) { TraceLog -Message " Analyze(): SOFTPAQ NEEDS UPDATE DUE TO UWP: $($SoftpaqHashEntry.UWPName)" TraceLog -Message " ... UWP Available Version: $($SoftpaqHashEntry.UWPVersion)" TraceLog -Message " ... UWP Installed Version: $($SoftpaqHashEntry.UWPInstallVersion)" TraceLog -Message " ... UWP Return code: $($SoftpaqHashEntry.UWPStatus)" } # if ( $DebugOutput ) } else { if ( $DebugOutput ) { TraceLog -Message " Analyze() SOFTPAQ DOES NOT INCLUDE UWP" } } # else if ( $a_UWPInfo[1] ) } # if ( $SoftpaqHashEntry.Status -ge 0 ) } # if ( $a_DvrReturnArray[0] ) } if ( $pSoftpaq.Category -match 'software' -or ` ($pSoftpaq.Category -match 'diagnostic') -or ` ($pSoftpaq.Category -match 'utility') ) { $SoftpaqHashEntry.Category = 'Software' ; ` $SoftpaqHashEntry.InstallVersion = $null ; ` $SoftpaqHashEntry.InstallDate = $null ; ` $SoftpaqHashEntry.Status = -1 ; ` # default to "-- SOFTWARE NOT INSTALLED" if ( $a_AnalyzeType -eq 'Array') { # $pApps='HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' # $pWOWApps='HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' # return $fs_AppVersion, $fs_AppDate, $fs_AppName $a_SoftwareFound = Find_Software $pSoftpaq $pSpqMetadata $pApps $pWOWApps } else { # 'XMLNode' $f_TargetApps = $pDriversList.SelectNodes("ImagePal/SystemInfo/SoftwareInstalled") $a_SoftwareFound = Find_Software $pSoftpaq $pSpqMetadata $f_TargetApps } if ( $a_SoftwareFound[0] ) { # if version exists ... # add found app info to hash table entry $SoftpaqHashEntry.InstallVersion = ($a_SoftwareFound[0]).split(' ')[0] $SoftpaqHashEntry.InstallDate = $a_SoftwareFound[1] if ( $a_AnalyzeType -like 'XMLNode') { # using a Capture Targe File $SoftpaqHashEntry.InstallVersion = $a_SoftwareFound.Version } if ( $SoftpaqHashEntry.InstallVersion ) { # handle Version where there is more than #.#.#.# in string if ( (Compare_Version $SoftpaqHashEntry.InstallVersion $pSoftpaq.Version) ) { $SoftpaqHashEntry.Status = 1 # "-- SOFTWARE UPDATE AVAILABLE" } else { $SoftpaqHashEntry.Status = 0 # "-- SOFTWARE UP TO DATE" } } # if ( $SoftpaqHashEntry.InstallVersion ) } else { # check if Software installed as UWP package # Get_UWPInfo(): $gu_CVAUWPName, $gu_CVAUWPVersion, $gu_AppxInstalledVersion $a_UWPInfo = Get_UWPInfo $pSpqMetadata $pInstalledAppxApps $a_UWPInstalledVersion = $a_UWPInfo[2] if ( $a_UWPInstalledVersion ) { $SoftpaqHashEntry.InstallVersion = $a_UWPInstalledVersion if ( (Compare_Version $SoftpaqHashEntry.InstallVersion $pSoftpaq.Version) ) { $SoftpaqHashEntry.Status = 1 # "-- SOFTWARE UPDATE AVAILABLE" } else { $SoftpaqHashEntry.Status = 0 # "-- SOFTWARE UP TO DATE" } } else { if ( $Script:RecommendedSoftware -and ( $pSoftpaq.Name -in $Script:RecommendedSWList ) ) { $SoftpaqHashEntry.Status = 1 # show as "-- SOFTWARE UPDATE AVAILABLE" # otherwise it won't be listed as Recommended for update } # if ( $Script:RecommendedSoftware ) } # else if ( $a_UWPInstalledVersion ) } # else if ( $a_SoftwareFound[0] ) } # if ( $pSoftpaq.Category -match 'software' -or ($pSoftpaq.Category -match 'diagnostic') ) return $SoftpaqHashEntry } # Function Analyze <###################################################################################### Function Get_OutputLine Searches the current system for a match for the Softpaq in question Parm: $pSoftpaq: Softpaq node entry (from Get-SoftpaqList) to match in device $pSpqMetadata: contents of Softpaq's CVA file $pDriversList: List of PnP installed drivers, OR Captured Config Devices list (XML format) Return: [0]Console string, [1]CSV string #>##################################################################################### Function Get_OutputLine { [CmdletBinding()] param( $pEntry, $pShowHWID ) $VerInstallDate = ($pEntry.InstallDate -split ' ')[0] ####################################### # setup the startup output string ####################################### $go_msg = "$($pEntry.SoftpaqID),$($pEntry.SoftpaqName),$($pEntry.SoftpaqVersion) $($pEntry.SoftpaqDate)" if ( $pEntry.InstallVersion ) { if ( $pEntry.InstallVersion -like 'missing' ) { $go_msg += ','+$pEntry.InstallVersion+' '+($VerInstallDate) } else { $go_msg += ',Installed '+$pEntry.InstallVersion+' '+($VerInstallDate) } } else { $go_msg += ',Not Installed' } # add Softpaq category $go_msg += ",($($pEntry.Category)-$($pEntry.ReleaseType))" # add UWP info switch ( $pEntry.UWPStatus ) { -1 { if ( $pEntry.UWPVersion ) { $go_msg += ",UWP:$($pEntry.UWPName):$($pEntry.UWPVersion)" } } 0 { $go_msg += ",UWP:$($pEntry.UWPName)" } 1 { $go_msg += ",UWP Update:$($pEntry.UWPName):$($pEntry.UWPVersion)/[Installed:$($pEntry.UWPInstallVersion)]" } } # switch ( $pEntry.UWPStatus ) # add HW ID matched to this driver if ( $pShowHWID -and $pEntry.CVAHWID ) { $go_msg += ",$($pEntry.CVAHWID)" } ####################################### # setup the startup output CSV string ####################################### $go_msgCSV = "$($pEntry.SoftpaqID),$($pEntry.SoftpaqName),$($pEntry.SoftpaqVersion)" # add the driver date if ( $pEntry.InstallVersion ) { $go_msgCSV += ','+$pEntry.InstallVersion } else { $go_msgCSV += ',' } # add Softpaq category, release type, and status $go_msgCSV += ",($($pEntry.Category)-$($pEntry.ReleaseType)),$($pEntry.Status)" # add UWP info matched to this driver switch ( $pEntry.UWPStatus ) { -1 { if ( $pEntry.UWPVersion ) { $go_msgCSV += ",$($pEntry.UWPName),$($pEntry.UWPVersion),,$($pEntry.UWPStatus)" } else { $go_msgCSV += ",,,," } } 0 { $go_msgCSV += ",$($pEntry.UWPName),$($pEntry.UWPVersion),$($pEntry.UWPInstallVersion),$($pEntry.UWPStatus)" } 1 { $go_msgCSV += ",$($pEntry.UWPName),$($pEntry.UWPVersion),$($pEntry.UWPInstallVersion),$($pEntry.UWPStatus)" } Default { $go_msgCSV += ",,,," } } # switch ( $pEntry.UWPStatus ) # add HW ID matched to this driver if ( $pShowHWID -and $pEntry.CVAHWID ) { $go_msgCSV += ",$($pEntry.CVAHWID)" } else { $go_msgCSV += "," } $go_msgCSV += ",$($pEntry.URL)" return $go_msg, $go_msgCSV } # Function Get_OutputLine() # ----------------------------------------------------------------------------------- ##################################################################################### # Start of Script ##################################################################################### $CurrLocation = Get-location TraceLog -Message "-- Obtaining Softpaq List for platform: [$ThisPlatformID] $ThisPlatformName -- OS: $OS/$OSVer" $SoftpaqsUpdateList = @() # List of Softpaqs that have updates $SoftpaqsNOUpdateList = @() # list of Softpaqs that do NOT require updates $SoftpaqsNOTInstalledList = @() # list of Softpaqs that are NOT installed TraceLog -Message '-- Retrieving PnP Drivers list for analysis' if ( -not $Script:TargetFile ) { #$PnpSignedDrivers = Get-CimInstance win32_PnpSignedDriver | where { $_.DriverVersion } $PnpSignedDrivers = Get-WMIObject win32_PnpSignedDriver | where { $_.DriverVersion } } TraceLog -Message '-- Linking to Registry entries (installed apps and UWP)' $InstalledApps = Get-ItemProperty 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' #$InstalledApps = Get-ItemProperty 'HKLM:\Software\Classes\Installer\Products\*' $InstalledWOWApps = Get-ItemProperty 'HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' #$InstalledAppxApps = Get-ChildItem 'HKLM:\SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\PackageRepository\Packages' $InstalledAppxApps = Get-AppxPackage TraceLog -Message '-- Accessing Reference File' $Script:XMLRefFileSolutions = $Script:XMlContent.SelectNodes("ImagePal/Solutions") $Script:XMLRefFileDevices = $Script:XMlContent.SelectNodes("ImagePal/Devices") $XMLRefFileUWPApps = $Script:XMlContent.SelectNodes("ImagePal/SystemInfo/UWPApps") TraceLog -Message '-- Analyzing Softpaqs for matches - Please wait...' foreach ( $Spq in $SoftpaqList ) { if ( $DebugOutput ) { TraceLog -Message "-- Analyzing Softpaq: $($Spq.id) - $($Spq.name)" } if ( -not $Script:LogFile -and (-not $NoDots) ) { TraceLog -Message "." -Type $TypeNoNewline } Try { $Error.Clear() $lineNum = ((get-pscallstack)[0].Location -split " line ")[1] # get code line # in case of failure $SpqMetadata = Get-SoftpaqMetadata $Spq.id -ErrorAction Stop # get CVA file for this Softpaq } catch { $Err = $error[0].exception # OPTIONAL: $error[0].exception.gettype().fullname if ( $Err -match '404' ) { TraceLog -Message "$($Spq.id): missing CVA file - Get-SoftpaqMetadata exception: on line number $($lineNum)" } else { if ( $DebugOutput ) { TraceLog -Message "$($Spq.id): Get-SoftpaqMetadata exception: on line number $($lineNum) - $($Err)" } } } finally { # Let's do the analysis if ( $TargetFile ) { # target XML file from runstring $SoftpaqEntry = Analyze $Spq $SpqMetadata $xmlTargetContent $InstalledApps $InstalledWOWApps $InstalledAppxApps $XMLRefFileUWPApps } else { # target is 'this' system $SoftpaqEntry = Analyze $Spq $SpqMetadata $PnpSignedDrivers $InstalledApps $InstalledWOWApps $InstalledAppxApps $XMLRefFileUWPApps } # add Softpaqs to report lists switch ( $SoftpaqEntry.Status ) { -1 { $SoftpaqsNOTInstalledList += $SoftpaqEntry } # "-- SOFTPAQ NOT INSTALLED" {-1} 0 { # "-- SOFTPAQ UP TO DATE" {0} if ( $SoftpaqEntry.UWPStatus -eq 1 ) { $SoftpaqsUpdateList += $SoftpaqEntry } else { $SoftpaqsNOUpdateList += $SoftpaqEntry } # if ( $SoftpaqEntry.UWPStatus -eq 1 ) } 1 { $SoftpaqsUpdateList += $SoftpaqEntry } # "-- SOFTPAQ UPDATE AVAILABLE" {1} } # switch ( $SoftpaqEntry.Status ) } # Try catch finally } # foreach ( $Spq in $SoftpaqList ) #################################################################### # finally report what we found - Update list first # NOTE: Use -l <LogFile> to redirect output #################################################################### if ( -not $NoDots ) {TraceLog -Message ' '} # create CSV output file with column header $Headers = "SoftpaqID,SoftpaqName,SoftpaqVersion,InstalledVersion,Category-ReleaseType,Status,UWPName,UWPVersion,UWPInstalledVersion,UWPStatus,HWID,URL" if ( $Script:CsvLog ) { $Headers | Out-File $Script:CsvLog -encoding ASCII } # 1. report on Driver/BIOS that have updates first (Software next) TraceLog -Message '-- Softpaq Updates' foreach ( $r in $SoftpaqsUpdateList ) { if ( $r.Category -notmatch 'software' ) { # Drivers/BIOS first $OutString = Get_OutputLine $r $ShowHWID TraceLog -Message $OutString[0] if ( $Script:CsvLog ) { $OutString[1] | Out-File $Script:CsvLog -encoding ASCII -Append } } # if ( $r.Category -notmatch 'software' ) } # foreach ( $r in $SoftpaqsUpdateList ) # 2. report on Software that have updates, includes 'HP Recommended' (with -r option) #TraceLog -Message '' ; TraceLog -Message '-- Softpaq Updates - Software' foreach ( $r in $SoftpaqsUpdateList ) { if ( $r.Category -match 'software' ) { # output Software last $OutString = Get_OutputLine $r $ShowHWID # $OutString[0]= msg, $OutString[1]= CSV msg string TraceLog -Message $OutString[0] if ( $Script:CsvLog ) { $OutString[1] | Out-File $Script:CsvLog -encoding ASCII -Append } } # if ( $r.Category -match 'software' ) } # foreach ( $r in $SoftpaqsUpdateList ) #################################################################### # NEXT: Softpaqs that do not need updating, unless not wanted #################################################################### if ( $All ) { # 3. report on Driver/BIOS that have updates first (Software next) if ( $SoftpaqsNOUpdateList.count -gt 0 ) { TraceLog -Message '' ; TraceLog -Message '-- Softpaqs Up to Date' } foreach ( $r in $SoftpaqsNOUpdateList ) { if ( $r.Category -notmatch 'software' ) { $OutString = Get_OutputLine $r $ShowHWID # $OutString[0]= msg, $OutString[1]= CSV msg string TraceLog -Message $OutString[0] if ( $Script:CsvLog ) { $OutString[1] | Out-File $Script:LogFile -encoding ASCII -Append } } } # foreach ( $r in $SoftpaqsNOUpdateList ) # 4. report on Software that have NO updates foreach ( $r in $SoftpaqsNOUpdateList ) { if ( $r.Category -match 'software' ) { # output Software last $OutString = Get_OutputLine $r $ShowHWID # $OutString[0]= msg, $OutString[1]= CSV msg string TraceLog -Message $OutString[0] if ( $Script:CsvLog ) { $OutString[1] | Out-File $Script:CsvLog -encoding ASCII -Append } } } # foreach ( $r in $SoftpaqsNOUpdateList ) # 5. report on Softpaqs not installed last if ( $SoftpaqsNOTInstalledList.count -gt 0 ) { #'' ; '-- Softpaqs NOT Installed' TraceLog -Message '' ; TraceLog -Message '-- Softpaq Updates - Software NOT Installed' foreach ( $r in $SoftpaqsNOTInstalledList ) { if ( $r.Category -match 'software' ) { $OutString = Get_OutputLine $r $ShowHWID # $OutString[0]= msg, $OutString[1]= CSV msg string TraceLog -Message $OutString[0] if ( $Script:Output2CSV ) { $OutString[1] | Out-File $Script:CsvLog -encoding ASCII -Append } } # if ( $r.Category -notmatch 'software' ) } # foreach ( $r in $SoftpaqsNOTInstalledList ) } } # if ( -not $UpdatesOnly ) if ( $Script:CsvLog ) { '' | Out-File $Script:CsvLog -encoding ASCII -Append # add empty line ',,,,,1=Update Available; 0=Up To Date; -1=NOT Installed' | Out-File $Script:CsvLog -encoding ASCII -Append } $endTime = get-date $elapsedTime = New-TimeSpan -Start $startTime -End $EndTime TraceLog -Message "-- Analyzer done in (min:sec) ($($elapsedTime.ToString("mm\:ss")))" #$elapsedTime.ToString("dd\.hh\:mm\:ss") Set-location $CurrLocation return $SoftpaqsUpdateList } Function Invoke-HPDriverUpdate { <# .Name HPDriverUpdate.ps1 .Synopsis Leverages Analyzer to install HP Softpaqs needed on a device by Category .DESCRIPTION Finds Driver Softpaqs that can update the current system, then updates them .Notes Author: Gary Blok/HP Inc 23.11.09 - initial release 23.11.10 - added override parameter (-OSVerOverride), which allows you to run in unsupported land - This is useful when you're running an unsupported OS on a device. This typically happens when you run a new OS on older hardware. 23.11.13 - added "WhatIf" support [https://learn.microsoft.com/en-us/powershell/utility-modules/psscriptanalyzer/rules/shouldprocess?view=ps-modules] - https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-shouldprocess?view=powershell-7.3 .Dependencies Requires HP Client Management Script Library HP Business class devices (as supported by HPIA and HP CMSL) Internet access. Analyzer downloads content from Internet .Parameters -DriverType -- [String] Driver Type Categories that you want to install. Default = ALL -details -- [switch] include HP Software HP recommends .Examples # check for current driver updates available and trigger the installs Invoke-HPDriverUpdate # check for current driver updates and trigger updates for network devices Invoke-HPDriverUpdate -DriverType Network # check for current driver updates and trigger updates for network devices while adding verbose to the install commandline Invoke-HPDriverUpdate -DriverType Network -details #> [CmdletBinding(SupportsShouldProcess=$true)] param( # [Parameter(Mandatory = $false)] # [String]$DriverType, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [ValidateSet("All","Audio", "Graphics", "Chipset", "FirmwareandDriver", "Network", "Keyboard", "MouseandInputDevices")] [string]$DriverType = "All", [switch]$OSVerOverride, [switch]$Details #Enables Verbose on the Softpaq Install Command ) # param if ($OSVerOverride){ $UpdatesAvailable = Invoke-HPAnalyzer -OSVerOverride } else { $UpdatesAvailable = Invoke-HPAnalyzer } $OSCurrent = Get-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' $OSVer = $OSCurrent.GetValue('DisplayVersion') $UBR = "$($OSCurrent.GetValue('CurrentBuild')).$($OSCurrent.GetValue('UBR'))" $WinOS = Get-CimInstance win32_operatingsystem # $OS = 'win'+$WinOS.version.split('.')[0] if ( $WinOS.BuildNumber -lt 22000 ) { $OS = 'Win10' } else { $OS = 'Win11' } $Model = $((Get-CimInstance -ClassName Win32_ComputerSystem).Model) $Platform = $((Get-CimInstance -ClassName win32_baseboard).Product) Write-Output "---------------------------------------------------------------" if ($UpdatesAvailable -match "-2"){ Write-Host "Unable to Find Reference File for this Platform $Platform with this OS $OS $OSVer, if you'd like to try going unsupported, use the -OSVerOverride parameter" -ForegroundColor Red break } Write-Host "Device Info: Platform $Platform | Model $Model" -ForegroundColor Green Write-Host "OS: $OS | OSVer: $OSVer | UBR: $UBR " -ForegroundColor green if ($OSVerOverride){ Write-Host "Running in OSVerOverride Mode - this is not supported by HP as these updates are not tested with this combination of hardware and OS" -ForegroundColor Red Write-Host "$script:OSOVerOverRideComment (the latest supported OS for this platform)" -ForegroundColor Red } if ($DriverType -eq "All"){ $UpdatesForDriverType = $UpdatesAvailable | Where-Object {$_.Category -notmatch "BIOS" -and $_.SubCategory -notmatch "Enabling" -and $_.Category -notmatch "Software"} } else { $UpdatesForDriverType = $UpdatesAvailable | Where-Object {$_.SubCategory -match $DriverType} } # NO Driver updates available, so setting the $UpdatesForDriverType to NULL if (!($UpdatesAvailable.Category -match "Driver")){ $UpdatesForDriverType = $null #Write-Output "No Driver Updates found" } if ($UpdatesForDriverType.Count -gt 0){ if (!(Test-Path -Path "C:\SWSetup")){ new-item -Path "C:\SWSetup" -ItemType Directory -Force | Out-Null } #Remove Deplicate Vendor Graphic Updates (Drop oldest Softpaq Date) $GraphicUpdates = $UpdatesForDriverType | Where-Object {$_.SubCategory -match "Graphics"} if (($GraphicUpdates.SoftpaqID).count -gt 1){ ForEach ($Vendor in ($GraphicUpdates.Vendor | Select-Object -Unique)){ #Write-Host $Vendor $VendorGraphicUpdates = $GraphicUpdates | Where-Object {$_.Vendor -match $Vendor} if ($VendorGraphicUpdates.count -gt 1){ $MinDate = ($VendorGraphicUpdates.SoftpaqDate | Select-Object -Unique| measure -Minimum).Minimum $DumpDriver = $VendorGraphicUpdates | Where-Object {$_.SoftpaqDate -eq $MinDate} $UpdatesForDriverType = $UpdatesForDriverType | Where-Object {$_.SoftpaqID -ne $DumpDriver.SoftpaqID} } } } foreach ($Update in $UpdatesForDriverType){ Write-Output "--------------------------------------------------" Write-Host "Found Updated Driver $($Update.SoftpaqName)" -ForegroundColor Cyan Write-Output " DriverType: $($Update.SubCategory)" Write-Output " Release Date: $($Update.SoftpaqDate)" Write-Output " Updated Version: $($Update.SoftpaqVersion)" Write-Output " Installed Verson: $($Update.InstallVersion)" Write-Output " SoftPaqID: $($Update.SoftpaqID)" #Start Update Process Write-Output " Starting Update...." if ($Details){ #Just adding -verbose to commandline if ($PSCmdlet.ShouldProcess("$($env:computername)","Get-Softpaq -Number $($Update.SoftpaqID) -Action silentinstall -DestinationPath C:\SWSetup -SaveAs C:\SWSetup\$($Update.SoftpaqID).exe -verbose")){ Write-Output " Get-Softpaq -Number $($Update.SoftpaqID) -Action silentinstall -DestinationPath C:\SWSetup -SaveAs C:\SWSetup\$($Update.SoftpaqID).exe -verbose" Get-Softpaq -Number $Update.SoftpaqID -Action silentinstall -quiet -DestinationPath "C:\SWSetup" -SaveAs "C:\SWSetup\$($Update.SoftpaqID).exe" -Verbose } else { # Code that should be processed if doing a WhatIf operation # Must NOT change anything outside of the function / script } } else { if ($PSCmdlet.ShouldProcess("$($env:computername)","Get-Softpaq -Number $($Update.SoftpaqID) -Action silentinstall -DestinationPath C:\SWSetup -SaveAs C:\SWSetup\$($Update.SoftpaqID).exe")){ Write-Output " Get-Softpaq -Number $($Update.SoftpaqID) -Action silentinstall -DestinationPath C:\SWSetup -SaveAs C:\SWSetup\$($Update.SoftpaqID).exe" Get-Softpaq -Number $Update.SoftpaqID -Action silentinstall -quiet -DestinationPath "C:\SWSetup" -SaveAs "C:\SWSetup\$($Update.SoftpaqID).exe" } else { # Code that should be processed if doing a WhatIf operation # Must NOT change anything outside of the function / script } } Write-Output " Completed Install of Softpaq" } } else { Write-Output "No Updates found for DriverType: $DriverType" } if (!($UpdatesAvailable.Category -match "Driver")){ $UpdatesAvailable if ($UpdatesAvailable -match "Cannot validate argument on parameter 'OsVer'"){ Write-Host "Try again with -OSVerOverride parameter to bypass supported OS check" -ForegroundColor Red } } } |