[PowerShell] / Get-HpProductInfo.ps1 Repository:
ViewVC logotype

View of /Get-HpProductInfo.ps1

Parent Directory Parent Directory | Revision Log Revision Log


Revision 18 - (download) (annotate)
Thu Dec 26 00:28:29 2013 UTC (10 years, 4 months ago) by ian
File size: 25276 byte(s)
The HP PartSurfer site changed a week or so back and broke that part of the script as well, part and sku data lookup now works again;
Warranty lookup is still broken and proving to be very stubborn to scrape the new site;
þÿ<#



.NOTES

 Written by Ian Cammarata  http://ian.cammarata.us

 Get-HpProductInfo.ps1 v0.3

 

This will probably only work for products sold in the U.S. 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





.SYNOPSIS

Query by SN to retreive HP product info from PartSufer and HP Business warranty lookup.





.EXAMPLE

PS> Get-HpProductInfo JPBCD3R1H3



#>



param(

    #The serial number to query.

    [Parameter( Mandatory = $True, Position = 0, ValueFromPipeline= $True )]

    [Alias( "SN" )]

    [String[]]

    $SerialNumber,

    

    #Output an object instead of an plain text.

    [Switch]

    [Alias( "Object" )]

    $OutputObject,



    #Purge cash for supplied SN(s) and fetch fresh data

    [Switch]

    [Alias( "Purge" )]

    $Refresh

)





BEGIN {

    Set-StrictMode -Version Latest



    ###### Set Constants

    #<#  ### uncomment this line for testing in ISE after initial run

    Set-Variable productObjectVersion -option Constant -value 0.2

    Set-Variable partSurferQueryUrl -option Constant -value "http://partsurfer.hp.com/Search.aspx?searchText="

    #Set-Variable hpWarrantyQueryUrl -option Constant -value "http://h20000.www2.hp.com/bizsupport/TechSupport/WarrantyResults.jsp?lang=en&cc=us&country=US&find=Display+Warranty+Information+%C2%BB"

    Set-Variable hpWarrantyStartUrl -option Constant -value "http://h20566.www2.hp.com/portal/site/hpsc/template.PAGE/public/wc/results/"

    Set-Variable hpWarrantyQueryUrl -option Constant -value "http://h20566.www2.hp.com/portal/site/hpsc/template.PAGE/public/wc/results/?spf_p.tpst=wcMain&spf_p.prp_wcMain=wsrp-navigationalState%3Daction%253Dsummary&javax.portlet.begCacheTok=com.vignette.cachetoken&javax.portlet.endCacheTok=com.vignette.cachetoken"

    Set-Variable cacheDir -option Constant -value (Join-Path $env:APPDATA "HpProductInfo_Cache")

    Set-Variable maxCacheAge -option Constant -value 90 #In Days

    #>



    ###### Prep

    if ( !( Test-Path $cacheDir ) ){ $null = New-Item -Type "Directory" -Path $cacheDir }



    ###### Default display property set

    $objectTemplateFile = Join-Path $cacheDir "HpProductObjectTemplate_v$($productObjectVersion).ps1xml"

    if ( !( Test-Path $objectTemplateFile ) ) {

        $template = "<?xml version='1.0' encoding='utf-8' ?>"

        $template += "<Types><Type><Name>System.Management.Automation.PSCustomObject</Name><Members><MemberSet>"

        $template += "<Name>PSStandardMembers</Name><Members><PropertySet><Name>DefaultDisplayPropertySet</Name><ReferencedProperties>"

        $template += "<Name>ProductNumber</Name>"

        $template += "<Name>SerialNumber</Name>"

        $template += "<Name>Description</Name>"

        $template += "<Name>WarrantyOnsite</Name>"

        $template += "<Name>Parts</Name>"

        $template += "</ReferencedProperties></PropertySet></Members></MemberSet></Members></Type></Types>"

        Out-File $objectTemplateFile -Encoding "UTF8" -InputObject $template -Force

    }

    if ( $PSVersionTable.PSVersion.Major -gt 2 ) {

        Update-TypeData $objectTemplateFile

    }

    elseif ( ! ( $host.Runspace.RunspaceConfiguration.Types | ? { $_.FileName -eq $objectTemplateFile } ) ) {

        Update-TypeData $objectTemplateFile

    }

}



PROCESS {

    Foreach ($SerialNumber in $SerialNumber) {

        $SerialNumber = $SerialNumber.Trim().ToUpper()

        ### Begin Check Cache

        $useCache = $false

        if ( $cacheHit = ls $cacheDir | ? { $_.Name -like "$($SerialNumber)_*" } ) {

            Write-Debug "Cache Hit!!! ($cacheHit)"

            $useCache = $true

            if ( $Refresh ) {

                $useCache = $false

            }

            elseif ( $cacheHit -notlike "*_v$($productObjectVersion).xml" ) {

                Write-Debug "Version Mismatch; Deleting... :-("

                $useCache = $false

            }

            elseif ( ( Get-Date ) -gt $cacheHit.CreationTime.AddDays(90) ) {

                Write-Debug "Stale Cache; Deleting... :-("

                $useCache = $false

            }



            if ( ! $useCache ) { Remove-Item ( Join-Path $cacheDir $cacheHit ) }

        }

        Write-Debug "Using Cache: $($useCache)"

        ### End Check Cache





        function downloadProductData () {

            ### 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)$($SerialNumber)")



            #Clean line breaks, tabs, multiple spaces, and blank space between tags

            $htData = $htData -replace "\n", "" -replace "\t", " " -replace "  ", "" -replace "> <", "><"

            

            ### Create psObject represinting the product

            $hpProduct = New-Object psObject



            ### Load generic sku data into the object

            $hpProduct | Add-Member NoteProperty SerialNumber $SerialNumber

            $null = $htData -match "<span id=`"ctl00_BodyContentPlaceHolder_lblProductNumber`">(.*?)</span>"

            $hpProduct | Add-Member NoteProperty ProductNumber $Matches[1]

            $null = $htData -match "<span id=`"ctl00_BodyContentPlaceHolder_lblDescription`">(.*?)</span>"

            $hpProduct | Add-Member NoteProperty Description $Matches[1]



            ### Add parts to psObject (Check boxes are no longer supplied by the site to determine part availability)

            $hpProduct | Add-Member NoteProperty Parts (New-Object psObject)

            $trMatches = Select-String "<tr class=`"[^`"]*RowStyle`">.*?</tr>" -inputObject $htData -AllMatches

            foreach ( $trMatch in $trMatches.Matches ){

                IF ( $trMatch.Value -notmatch ".*(no longer supplied|Not Available).*" )

                {

                    $spanMatches = Select-String "<span.*?>(.*?)</span>" -inputObject $trMatch.Value -AllMatches

                    #"$($spanMatches.Matches[0].Groups[1].Value)`t$($spanMatches.Matches[1].Groups[1].Value)"

                    $partObject = New-Object psObject

                    $partObject | Add-Member NoteProperty PartNumber $spanMatches.Matches[0].Groups[1].Value

                    $partObject | Add-Member NoteProperty Description $spanMatches.Matches[1].Groups[1].Value

                    $hpProduct.Parts | Add-Member NoteProperty $partObject.PartNumber $partObject

                }

            }





            <#

            ### 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 "<br>"

            while ($htData -match "<td[^>]*>\s*([\w\s:]*)\s*</td>\s*<td[^>]*>\s*(\d{1,2} \w{3} \d{4})\s*</td>\s*<td[^>]*>\s*(\d{1,2} \w{3} \d{4})\s*</td>" ) {

                $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 = ( '{0:MMM d yyyy}' -f ( Get-Date $warranty[$i+1] ) ); End = ( '{0:MMM d yyyy}' -f ( Get-Date $warranty[$i+2] ) ) }

              $i += 3

            }#>



            ### Download and parse warranty i nfo

<#

Parametersapplication/x-www-form-urlencoded

rows[0].item.countryCode	US

rows[0].item.serialNumber	CND120CJH0

rows[1].item.countryCode	US

rows[1].item.serialNumber	

rows[2].item.countryCode	US

rows[2].item.serialNumber	

rows[3].item.countryCode	US

rows[3].item.serialNumber	

rows[4].item.countryCode	US

rows[4].item.serialNumber	

rows[5].item.countryCode	US

rows[5].item.serialNumber	

rows[6].item.countryCode	US

rows[6].item.serialNumber	

rows[7].item.countryCode	US

rows[7].item.serialNumber	

rows[8].item.countryCode	US

rows[8].item.serialNumber	

rows[9].item.countryCode	US

rows[9].item.serialNumber	

submitButton	Submit

###################################################

Source

rows%5B0%5D.item.serialNumber=CND120CJH0&rows%5B0%5D.item.countryCode=US&rows%5B1%5D.item.serialNumber=&rows%5B1%5D.item.countryCode=US&rows%5B2%5D.item.serialNumber=&rows%5B2%5D.item.countryCode=US&rows%5B3%5D.item.serialNumber=&rows%5B3%5D.item.countryCode=US&rows%5B4%5D.item.serialNumber=&rows%5B4%5D.item.countryCode=US&rows%5B5%5D.item.serialNumber=&rows%5B5%5D.item.countryCode=US&rows%5B6%5D.item.serialNumber=&rows%5B6%5D.item.countryCode=US&rows%5B7%5D.item.serialNumber=&rows%5B7%5D.item.countryCode=US&rows%5B8%5D.item.serialNumber=&rows%5B8%5D.item.countryCode=US&rows%5B9%5D.item.serialNumber=&rows%5B9%5D.item.countryCode=US&submitButton=Submit

#>

<#

wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";

string HtmlResult = wc.UploadString(URI, myParameters);

#>

            <#

            $ErrorActionPreference = "Stop" #Needed so script won't continue if the web server returns an error

            #$htClient.Headers["Content-Type"] = "application/x-www-form-urlencoded"

            $htClient.Headers.Set( "Content-Type", "application/x-www-form-urlencoded" )

            #$htData = $htClient.DownloadString("$($partSurferQueryUrl)$($SerialNumber)")

            $htData = $htClient.UploadString( $hpWarrantyQueryUrl, "rows[0].item.serialNumber=$($SerialNumber)&rows[0].item.countryCode=US" )

            $htData = -join $htData[$htData.IndexOf("<body")..($htData.LastIndexOf("</body>")+6)]

            $htData = $htData -replace '(?sx:<script[\s\S]*?</script[\s\S]*?>)' -replace '(?sx:<noscript[\s\S]*?</noscript[\s\S]*?>)'

            $htData = $htData -replace ' & ', " and " -replace "&\w{2,6};"

            #>

            



            $hpProduct | Add-Member NoteProperty __QueryDate (Get-Date)

            $hpProduct | Add-Member NoteProperty __productObjectVersion $productObjectVersion



            $hpProduct | Export-Clixml (Join-Path $cacheDir "$($hpProduct.SerialNumber)_$($hpProduct.ProductNumber)_v$($productObjectVersion).xml")

            return $hpProduct

        }





        #Import line is potentially error prone, make it more specific later on

        if ( $useCache ) { $hpProduct = Import-Clixml ( Join-Path $cacheDir "$($SerialNumber)_*" ) }

        else { $hpProduct = downloadProductData }





        if ( $OutputObject ) {

            $hpProduct

        }

        Else {

            $lineLen = 75



            "-" * $lineLen



            "Serial Number:`t$($hpProduct.SerialNumber)"

            "Product Number:`t$($hpProduct.ProductNumber)"

            "Description:`t$($hpProduct.Description)"



            <#"-" * $lineLen



            "Warranty:"

            foreach ( $warrantyItem in $hpProduct | Get-Member | ? { $_.Name -like "Warranty*" } | % { $_.Name } ) {

              "$($warrantyItem):"

              "     Start: $($hpProduct.$warrantyItem.Start)     End: $($hpProduct.$warrantyItem.End)"

            }#>



            "-" * $lineLen

            $parts = $hpProduct.Parts | get-member -MemberType "NoteProperty"

            "Available Parts: $($parts.Length)"



            "-" * $lineLen

            foreach ( $part in $parts | % { $_.Name } ) {

                "$($hpProduct.Parts.$part.PartNumber) - $($hpProduct.Parts.$part.Description)"

            }

            "-"*$lineLen

        }

    }

}

Contact
ViewVC Help
Powered by ViewVC 1.0.4