Public/Catalog/Get-CatalogHPSystem.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
<#
.SYNOPSIS
Converts the HP Client Catalog for Microsoft System Center Product to a PowerShell Object
 
.DESCRIPTION
Converts the HP Client Catalog for Microsoft System Center Product to a PowerShell Object
Requires Internet Access to download HpCatalogForSms.latest.cab
 
.PARAMETER Component
Filter the results based on these Components:
Software
Driver
Firmware
Accessories Firmware and Driver
BIOS
 
.PARAMETER Compatible
If you have a HP System, this will filter the results based on your
ComputerSystem Product (Win32_BaseBoard Product)
 
.EXAMPLE
Get-CatalogHPSystem
Don't do this, you will get an almost endless list
 
.EXAMPLE
$Result = Get-CatalogHPSystem
Yes do this. Save it in a Variable
 
.EXAMPLE
Get-CatalogHPSystem -Component BIOS | Out-GridView
Displays all the HP BIOS updates in GridView
 
.LINK
https://osd.osdeploy.com/module/functions
 
.NOTES
#>

function Get-CatalogHPSystem {
    [CmdletBinding()]
    param (
        [ValidateSet('Software','Firmware','Driver','Accessories Firmware and Driver','BIOS')]
        [string]$Component,
        [switch]$Compatible
    )
    #=======================================================================
    # Paths
    #=======================================================================
    $CatalogState           = 'Online' #Online, Build, Local, Offline
    $CatalogOnlinePath      = 'https://hpia.hpcloud.hp.com/downloads/sccmcatalog/HpCatalogForSms.latest.cab'
    $CatalogBuildFolder     = $env:TEMP
    $CatalogBuildFileName   = 'HpCatalogForSms.xml'
    $CatalogBuildPath       = Join-Path $CatalogBuildFolder $CatalogBuildFileName
    $CatalogLocalPath          = Join-Path $env:TEMP 'CatalogHPSystem.xml'
    $CatalogOfflinePath     = "$($MyInvocation.MyCommand.Module.ModuleBase)\Files\Catalogs\CatalogHPSystem.xml"
    $CatalogLocalCabName      = [string]($CatalogOnlinePath | Split-Path -Leaf)
    $CatalogLocalCabPath     = Join-Path $env:TEMP $CatalogLocalCabName
    #=======================================================================
    # Test CatalogState Local
    #=======================================================================
    if (Test-Path $CatalogLocalPath) {

        #Get-Item to determine the age
        $GetItemCatalogLocalPath = Get-Item $CatalogLocalPath

        #If the local is older than 12 hours, delete it
        if (((Get-Date) - $GetItemCatalogLocalPath.LastWriteTime).TotalHours -gt 12) {
            Write-Verbose "Removing previous Offline Catalog"
        }
        else {
            $CatalogState = 'Local'
        }
    }
    #=======================================================================
    # Test CatalogState Online
    #=======================================================================
    if ($CatalogState -eq 'Online') {
        if (Test-WebConnection -Uri $CatalogOnlinePath) {
            #Catalog is online and can be downloaded
        }
        else {
            $CatalogState = 'Offline'
        }
    }
    #=======================================================================
    # CatalogState Online
    # Need to get the Online Catalog to Local
    #=======================================================================
    if ($CatalogState -eq 'Online') {
        Write-Verbose "Source: $CatalogOnlinePath"
        Write-Verbose "Destination: $CatalogLocalCabPath"
        (New-Object System.Net.WebClient).DownloadFile($CatalogOnlinePath, $CatalogLocalCabPath)

        #Make sure the file downloaded
        if (Test-Path $CatalogLocalCabPath) {
            Write-Verbose "Expand: $CatalogLocalCabPath"
            Expand "$CatalogLocalCabPath" -F:"$($CatalogBuildFileName)" "$CatalogBuildFolder" | Out-Null

            if (Test-Path $CatalogBuildPath) {
                $CatalogState = 'Build'
            }
            else {
                Write-Verbose "Could not expand $CatalogLocalCabPath"
                $CatalogState = 'Offline'
            }
        }
        else {
            $CatalogState = 'Offline'
        }
    }
    #=======================================================================
    # CatalogState Build
    #=======================================================================
    if ($CatalogState -eq 'Build') {
        Write-Verbose "Getting the HP Platform List catalog to map System Id to model names."
        $PlatformCatalogHashTable = @{}
        Get-CatalogHPPlatformList | ForEach-Object{
            $PlatformCatalogHashTable.Add($_.SystemId,$_.SupportedModel)
        }
        
        
        Write-Verbose "Reading the System Catalog at $CatalogBuildPath"
        [xml]$XmlCatalogContent = Get-Content $CatalogBuildPath -ErrorAction Stop
        $CatalogVersion = Get-Item $CatalogBuildPath | Select-Object -ExpandProperty LastWriteTimeUtc | Get-Date -Format yy.MM.dd
        $Packages = $XmlCatalogContent.SystemsManagementCatalog.SoftwareDistributionPackage

        Write-Verbose "Building the System Catalog"
        $Packages = $Packages | Where-Object{$_.Properties.PublicationState -ne 'Expired'}
        
        #Only Windows 10 applicable packages
        $Packages = $Packages | Where-Object{$_.IsInstallable.And.Or.And.WindowsVersion.MajorVersion -contains '10'}
        
        $Result = Foreach($Item in $Packages){
            #SystemId
            $SystemIdMatchInfo = $Item.InstallableItem.ApplicabilityRules.IsInstallable.And.WmiQuery.wqlquery | Where-Object{$_ -like "*from Win32_BaseBoard*"} | Select-String -Pattern '%(.{4})%' -AllMatches
            $SupportedSystemId = [array]($SystemIdMatchinfo.Matches.Groups | Where-Object{$_.Name -eq 1} | Select-Object -ExpandProperty Value)
            
            #SupportedModel
            $SupportedModel = foreach($Id in $SupportedSystemId){
                $PlatformCatalogHashTable."$($Id)"
            }
            $SupportedModel = $SupportedModel | Select-Object -Unique
            
            #Title
            $TitleMatchInfo = $Item.LocalizedProperties | Where-Object{$_.Language -eq 'en'} | Select-Object -ExpandProperty Title | Select-String -Pattern "^(.*) \[(.*)\]$"
            If($TitleMatchInfo){#Remove the version in the title
                $Title = $TitleMatchInfo.Matches.Groups[1].Value
            }Else{#No version in title
                $Title = $Item.LocalizedProperties | Where-Object{$_.Language -eq 'en'} | Select-Object -ExpandProperty Title
            }
            
            #[Version] + Description
            #There's always a version in the description so far, let's hope HP stays consistent...
            $DescriptionMatchInfo = $Item.LocalizedProperties | Where-Object{$_.Language -eq 'en'} | Select-Object -ExpandProperty Description | Select-String -Pattern "^\[(.*)\] (.*)$"
            
            $ObjectProperties = [Ordered]@{
                CatalogVersion          = $CatalogVersion
                Component            = $Item.Properties.ProductName
                CreationDate         = ($Item.Properties.CreationDate) | Get-Date -Format yy.MM.dd
                Title                = $Title
                Version              = ($DescriptionMatchInfo.Matches.Groups[1].Value).Trim('.')
                SupportedSystemId    = $SupportedSystemId
                SupportedModel       = $SupportedModel
                Description          = ($DescriptionMatchInfo.Matches.Groups[2].Value)
                SoftPaqId            = $Item.UpdateSpecificData.KBArticleID
                Program              = $Item.InstallableItem.CommandLineInstallerData.Program
                ProgramArguments     = $Item.InstallableItem.CommandLineInstallerData.Arguments
                ProgramDownloadUrl   = $Item.InstallableItem.OriginFile.OriginUri
                MoreInfoUrl          = $Item.Properties.MoreInfoUrl
            }
            New-Object -TypeName PSObject -Property $ObjectProperties
        }
        
    
        Write-Verbose "Exporting Offline Catalog to $CatalogLocalPath"
        $Result = $Result | Sort-Object CreationDate -Descending
        $Result | Export-Clixml -Path $CatalogLocalPath
    }
    #=======================================================================
    # CatalogState Local
    #=======================================================================
    if ($CatalogState -eq 'Local') {
        Write-Verbose "Reading the Local System Catalog at $CatalogLocalPath"
        $Result = Import-Clixml -Path $CatalogLocalPath
    }
    #=======================================================================
    # CatalogState Offline
    #=======================================================================
    if ($CatalogState -eq 'Offline') {
        Write-Verbose "Reading the Offline System Catalog at $CatalogOfflinePath"
        $Result = Import-Clixml -Path $CatalogOfflinePath
    }
    #=======================================================================
    # Compatible
    #=======================================================================
    if ($PSBoundParameters.ContainsKey('Compatible')) {
        $MyComputerProduct = Get-MyComputerProduct
        Write-Verbose "Filtering XML for items compatible with Product $MyComputerProduct"
        $Result = $Result | Where-Object {$_.SupportedSystemID -contains $MyComputerProduct}
    }
    #=======================================================================
    # Component
    #=======================================================================
    if ($PSBoundParameters.ContainsKey('Component')) {
        Write-Verbose "Filtering XML for $Component"
        switch($Component){
            'BIOS'{
                $Result = $Result | Where-Object{$_.Component -eq 'Firmware' -and $_.Description -like "*NOTE: THIS BIOS UPDATE*"}
            }
            'Firmware'{
                $Result = $Result | Where-Object{$_.Component -eq 'Firmware' -and $_.Description -notlike "*NOTE: THIS BIOS UPDATE*"}
            }
            default{
                $Result = $Result | Where-Object {$_.Component -eq $Component}
            }
        }
    }
    #=======================================================================
    # Component
    #=======================================================================
    $Result | Sort-Object -Property CreationDate -Descending
    #=======================================================================
}