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 .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 $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 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') ) { $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) ) { $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 } } 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 "---------------------------------------------------------------" 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 } } } |