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

View of /Get-LenovoProductInfo.ps1

Parent Directory Parent Directory | Revision Log Revision Log


Revision 35 - (download) (annotate)
Sun Oct 12 17:15:47 2014 UTC (9 years, 6 months ago) by ian
File size: 20648 byte(s)
updated code for retrieving Product Name to work with updated Lenovo site;
þÿ<#



.NOTES

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

 Get-LenovoProductInfo.ps1 v0.3

 

 Will this only work for products sold in the U.S.?





To Do:

 -Generate a proper object (this will allow tab completion and easier programmatic use)



SNs for testing:

 LRNMV31 | 0301-24U | ThinkPad Edge 15

 R9002F1V | 20A8Z05QUS | ThinkPad X1 Carbon





.SYNOPSIS

Query by SN to retreive Lenovo warranty, product name and type, and parts.





.EXAMPLE

PS> Get-LenovoProductInfo MJDGZE4



#>



param(

    #The serial number to query.

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

    [Alias( "SN" )]

    [String[]]

    $SerialNumber,



    #Search string for parts listing.

    [Parameter( Position = 1 )]

    [Alias( "Part" )]

    $PartQuery,

    

    #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

    if ( $Script:PSBoundParameters.ContainsKey("Debug") ) { $DebugPreference = "Continue" } ### For some reason I was getting first 3 debug lines output in the Process block even with using -Debug, but none afterwards



    ###### Set Constants

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

    Set-Variable productObjectVersion -option Constant -value 0.4

    Set-Variable lenovoWarrantyUrl -option Constant -value "https://csp.lenovo.com/ibapp/il/WarrantyStatus.jsp"

    Set-Variable lenovoProductDescriptionUrl -option Constant -value "http://support.lenovo.com/services/us/en/advancedsearch/getsearchresult/1c2d5342-a15b-4828-9095-13e5d52f9df6?dataSource=aca55143-0507-4b4d-a559-65147c1dec9a&SearchKey="

    Set-Variable lenovoPartsUrl -option Constant -value "http://support.lenovo.com/templatedata/Web%20Content/JSP/partsLookup.jsp"

    Set-Variable cacheDir -option Constant -value (Join-Path $env:APPDATA "LenovoProductInfo_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 "LenovoProductObjectTemplate_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 {

    Function CleanHtml($htData) {

        Return $htData -replace "&nbsp;", "" -replace "(\r|\f|\n)*", "" -replace "\t", " " -replace "  ", "" -replace "> <", "><" -replace "<img[^>]*>", "" -replace "</?b>", ""

    }

    Foreach ($SerialNumber in $SerialNumber) {

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



        Write-Debug ">> Check cache for XML copy of data"

        $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)"

        Write-Debug "<< End Check Cache"





        function downloadProductData () {

            Write-Debug "/!\Begin critical section/!\ Any errors here break the entire script."

            $ErrorActionPreference = "Stop"





            Write-Debug "Set up httpWebRequest for Warranty lookup"

            [net.httpWebRequest] $webReq = [net.webRequest]::create($lenovoWarrantyUrl)

            $webReq.Method = "POST"



            $postData = "type=&serial=$($SerialNumber)&selLanguage=EN&country=897&iws=off&sitestyle=lenovo"

            $postBuffer = [Text.Encoding]::Ascii.GetBytes($postData)

            $webReq.ContentLength = $postBuffer.Length

            $webReq.ContentType = "application/x-www-form-urlencoded"

            $reqStr = $webReq.GetRequestStream()

            $reqStr.Write( $postBuffer, 0, $postBuffer.Length)

            $reqStr.Flush()

            $reqStr.Close()



            [net.httpWebResponse] $webResp = $webReq.GetResponse()

            $strRdr = New-Object IO.StreamReader($webResp.GetResponseStream())

            $htData = CleanHtml( $strRdr.ReadToEnd() )

            $webResp.Close()

            

            $warrantyHtData = $htData -replace ".*<!-- Warranty information Cycle Start-->", "" -replace "Excluding:.*", "" -replace "End Date:", ""

            $skuData = (Select-String "<td[^>]*>([^<:]+?)</td>" -InputObject $warrantyHtData -AllMatches).Matches | % {$_.Groups[1].Value}





            Write-Debug "Create psObject representing the product"

            $lenovoProduct = New-Object psObject





            Write-Debug "Load generic sku data into the object"

            $lenovoProduct | Add-Member NoteProperty ProductID $skuData[0]

            $lenovoProduct | Add-Member NoteProperty Type ($skuData[1] -split "-")[0]

            $lenovoProduct | Add-Member NoteProperty Model ($skuData[1] -split "-")[1]

            $lenovoProduct | Add-Member NoteProperty SerialNumber $skuData[2]

            $lenovoProduct | Add-Member NoteProperty Location $skuData[3]

            $lenovoProduct | Add-Member NoteProperty WarrantyExpiration $skuData[4]



            $ErrorActionPreference = "Continue"

            Write-Debug "/!\End critical section/!\"





            Write-Debug "Filter parts table rows out of the HTML."

            $null = $htData -match "<table[^>]*PartsTable.*?</table>"

            $trData = (Select-String "<tr><td[^>]*>[^<]*</td><td[^>]*>([^-<]*)</td><td[^>]*>([^<]*)</td></tr>" -InputObject $Matches[0] -AllMatches).Matches





            Write-Debug "Add FRUs to the product object."

            $lenovoProduct | Add-Member NoteProperty FRUs (New-Object psobject)

            foreach ( $tr in $trData ){

                $partObject = New-Object psObject

                $partObject | Add-Member NoteProperty FRU $tr.Groups[1].Value

                $partObject | Add-Member NoteProperty Description $tr.Groups[2].Value

                $lenovoProduct.FRUs | Add-Member NoteProperty $partObject.FRU $partObject -ErrorAction "SilentlyContinue"

            }





            Write-Debug "Create WebClient to query ProductName"

            $htClient = New-Object System.Net.Webclient

            #Query by product type

            $htData = $htClient.DownloadString("$($lenovoProductDescriptionUrl)$($lenovoProduct.ProductID)")

            

            #Navigate to result page

            $null = $htData -match '<a href="(.*?)">'

            $htData = cleanHtml( $htClient.DownloadString("http://support.lenovo.com/$($Matches[1])") )

            

            $null = $htData -match 'class="product-detail-title">(.*?)<'

            $lenovoProduct | Add-Member NoteProperty ProductName ($Matches[1] -replace ".*>" -replace " $($lenovoProduct.ProductID)" -replace " \(.*?\)")



          

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

            $lenovoProduct | Add-Member NoteProperty __productObjectVersion $productObjectVersion



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

            Return

        }





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

        if ( -not $useCache ) { downloadProductData }



        $lenovoProduct = Import-Clixml ( Join-Path $cacheDir "$($SerialNumber)_*" )



        if ( $OutputObject ) {

            $lenovoProduct

        }

        Else {

            $lineLen = 75



            "%ˆ" * $lineLen



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

            "Product ID:`t$($lenovoProduct.ProductID )"

            "Product Name:`t$($lenovoProduct.ProductName)"

            "Warranty End:`t$($lenovoProduct.WarrantyExpiration)"

            ""

            

            

            $parts = $lenovoProduct.FRUs | get-member -MemberType "NoteProperty"

            $partsTxt = @()

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

                if ( $PartQuery ) {

                    if ( $lenovoProduct.FRUs.$part.Description -match ".*$($PartQuery).*" ) {

                        $partsTxt += "$($lenovoProduct.FRUs.$part.FRU) - $($lenovoProduct.FRUs.$part.Description)"

                    }

                }

                Else { $partsTxt += "$($lenovoProduct.FRUs.$part.FRU) - $($lenovoProduct.FRUs.$part.Description)" }  

            }

            "FRUs$(if ( $PartQuery ) {" matching query '$($PartQuery)'"}): $($partsTxt.Length)"

            "%" * $lineLen

            $partsTxt

            

            "%ˆ"*$lineLen

        }

    }

}

Contact
ViewVC Help
Powered by ViewVC 1.0.4