################################################## # # Written by Ian Cammarata # Get-HpProductInfo.ps1 v0.1 # ################################################## # # Usage: # Get-HpProductInfo < serial number > # Ex: # Get-HpProductInfo JPBCD3R1H3 # ################################################## # # Notes: # -Will probably only work for products sold in the US unless you change the country # codes in $hpWarrantyQueryURL and the $htClient.Headers.set(...Cookie... # # To Do: # -Make it a proper PowerShell script (receive piped input, input validation, multiple SNs at once) # -Cache objects to an XML file for faster loading if the same SN is queried again. # -Multi-threading the http downloads and multiple retry attemps (partsufer is so unreliable lately) # -Option to filter parts output # # SNs for testing: CND120CJH0, CNU305BP9N, CNFKF52058, JPBCD3R1H3 # ################################################## Set-StrictMode -Version Latest $lookupSn = "CND120CJH0" if ($args) { $lookupSn = $args[0] } $partSurferQueryUrl = "http://partsurfer.hp.com/Search.aspx?searchText=" $hpWarrantyQueryUrl = "http://h20000.www2.hp.com/bizsupport/TechSupport/WarrantyResults.jsp?lang=en&cc=us&country=US&find=Display+Warranty+Information+%C2%BB" ### Create WebClient and cookie needed for PartSurfer $htClient = New-Object System.Net.Webclient $htClient.Headers.Set([System.Net.HttpRequestHeader]::Cookie, "Country=United%20States") ### Download and clean PartSurfer HTML so it can be parsed into XML $ErrorActionPreference = "Stop" #Needed so script won't continue if the web server returns an error $htData = $htClient.DownloadString("$($partSurferQueryUrl)$($lookupSn)") $htData = -join $htData[$htData.IndexOf("")+6)] $htData = $htData -replace '(?sx:)' -replace '(?sx:)' $htData = $htData -replace ' & ', " and " -replace "&\w{2,6};" $partSurferXml = [xml]$htData ### Parse collections of data $ErrorActionPreference = "SilentlyContinue" #Needed so filtering by ID won't generate an error on nodes with no ID property $partsHash = @{} $partSurferXml.SelectNodes("//span") | ? { $_.id -like "*gridSpareBOM_ctl*" -and $_.'#text' -notlike "*N/A*" } | % { $partsHash[$_.id] = $_.'#text' } $orderCheckboxArray = @() $partSurferXml.SelectNodes("//input") | ? { $_.id -like "*chkSpareBOM" } | % { $orderCheckboxArray += $_.id } $skuDataHash = @{} $partSurferXml.SelectNodes("//span") | ? { $_.id -like "*lbl*" -and $_.id -notlike "*BOM*" -and $_.id -notlike "*text*" } | % { $skuDataHash[$_.id] = $_.'#text' } $ErrorActionPreference = "Continue" ### Create psObject and start adding to it $hpProduct = New-Object psObject foreach ( $skuDatum in $skuDataHash.GetEnumerator() ){ $propName = "" switch -wildcard ($skuDatum.Name) { "*SerialNumber" { $propName ="SerialNumber" } "*ProductNumber" { $propName ="ProductNumber" } "*Description" { $propName ="Description" } } if ( $propName ) { $hpProduct | Add-Member NoteProperty $propName $skuDatum.Value } } $hpProduct | Add-Member NoteProperty Parts (New-Object psObject) ### Download and parse warranty info -- Page is too messy to clean for XML casting, will just scrape with regex $ErrorActionPreference = "Stop" #Needed so script won't continue if the web server returns an error $htData = $htClient.DownloadString("$($hpWarrantyQueryUrl)&sn=$($hpProduct.SerialNumber)&pn=$($hpProduct.ProductNumber)") $ErrorActionPreference = "Continue" $warranty = @() $htData = $htData -replace "
" while ($htData -match "]*>\s*([\w\s:]*)\s*\s*]*>\s*(\d{1,2} \w{3} \d{4})\s*\s*]*>\s*(\d{1,2} \w{3} \d{4})\s*" ) { $warranty += $Matches[1..3] $htData = $htData.Replace($Matches[0],1) } $warranty = $warranty -replace "wty: |HWM |HP |HW |Maintenance |Support |for| " ### Add warranty data to psObject $i = 0 while ( $i -lt $warranty.Length ){ #"$($warranty[$i])`t`tStart: $($warranty[$i+1])`t`tEnd: $($warranty[$i+2])" $hpProduct | Add-Member NoteProperty "Warranty$($warranty[$i])" @{ Start = ( Get-Date $warranty[$i+1] ); End = ( Get-Date $warranty[$i+2] ) } -force $i += 3 } ### Add orderable parts to psObject foreach ( $cb in $orderCheckboxArray ) { $null = $cb -match ".*(_ctl\d{2,3}_).*" $curPartData = $partsHash.GetEnumerator() | ? { $_.Name -like "*$($Matches[1])*" } $partObject = New-Object psObject foreach ( $part in $curPartData.GetEnumerator() ) { $propName = "" switch -wildcard ($part.Name) { "*spart1" { $propName ="PartNumber" } "*desc1" { $propName ="Description" } "*Enhanced" { $propName ="EnhancedDescription" } "*Category1" { $propName ="Category" } "*CSR1" { $propName ="CSR" } "*Rohs1" { $propName ="ROHS" } "*tech1" { $propName ="Tech" } } if ( $propName ) { $partObject | Add-Member NoteProperty $propName $part.Value } } $hpProduct.Parts | Add-Member NoteProperty $partObject.PartNumber $partObject } ### Cleanup (probably not necessary?) #Remove-Variable "a", "b" $hpProduct