Thursday 28 November 2013

Custom WMI Class in SCCM 2012 for Hardware Warranty Information Part 1

Based on my previous post re Custom WMI Classes (http://sccmshenanigans.blogspot.co.uk/2013/11/custom-wmi-classes-and-reporting-into.html) here's another custom class and scripts for obtaining hardware warranty information.

Creating the new class

As with the previous example, run Powershell and run the command Get-WMIObject -class WarrantyDetails and you should get an error re Invalid Class

So, same as with the MonitorDetails class, the code below will create the WarrantyDetails custom WMI class

function Create-Wmi-Class()
{
    $newClass = New-Object System.Management.ManagementClass("root\cimv2", [String]::Empty, $null);

    $newClass["__CLASS"] = "WarrantyDetails";

    $newClass.Qualifiers.Add("Static", $true)
    $newClass.Properties.Add("SerialNumber", [System.Management.CimType]::String, $false)
    $newClass.Properties["SerialNumber"].Qualifiers.Add("key", $true)
    $newClass.Properties["SerialNumber"].Qualifiers.Add("read", $true)
    $newClass.Properties.Add("ProductNumber", [System.Management.CimType]::String, $false)
    $newClass.Properties["ProductNumber"].Qualifiers.Add("read", $true)
    $newClass.Properties.Add("WarrantyInfo", [System.Management.CimType]::String, $false)
    $newClass.Properties["WarrantyInfo"].Qualifiers.Add("read", $true)
    $newClass.Properties.Add("WarrantyDate", [System.Management.CimType]::String, $false)
    $newClass.Properties["WarrantyDate"].Qualifiers.Add("read", $true)
    $newClass.Put()
}

# Check whether we already created our custom WMI class on this PC, if not, create it
[void](Get-WMIObject WarrantyDetails -ErrorAction SilentlyContinue -ErrorVariable wmiclasserror)
if ($wmiclasserror)
{
    try { Create-Wmi-Class }
    catch
    {
        "Could not create WMI class"
        Exit 1
    }
}

$sSerialNumber = ((Get-WmiObject -Class win32_bios).serialnumber).trim()
$sProductNumber = $null
$sProductNumber = (( Get-WmiObject -ComputerName $ComputerName -namespace "root\hp\InstrumentedBIOS" -Query "select * from HP_BIOSSetting" | Where-Object { ($_.Name -eq "SKU Number") -or ($_.Name -eq "Product Number") } ).Value).trim()

if ($sproductnumber -eq $null)
{
    $sProductNumber = (Get-ItemProperty HKLM:\\HARDWARE\Description\System\BIOS).SystemSKU
}

# Clear WMI
Get-WmiObject WarrantyDetails | Remove-WmiObject

# And store the data in WMI
[Void](Set-WmiInstance -Path \\.\root\cimv2:WarrantyDetails -Arguments @{SerialNumber=$sSerialNumber; ProductNumber=$sProductNumber})


You may need to customise the $sProductNumber information - the example above is specifically for HP kit.

Once the above class has been created, retest on your machine and you should see information



We'll come back to the blank WarrantyDate and WarrantyInfo later.

Following the steps in the previous post, add the new class to the Hardware Inventory classes on Default Client Settings.  Again, watching the dataldr.log file you should see new SQL tables and views created.

When creating the baseline item, the discovery script is almost identical to the previous post:


Discovery Script (Script Language : Powershell)

$ClassInfo = Get-WMIObject WarrantyDetails -ErrorAction SilentlyContinue -ErrorVariable wmiclasserror

if ($wmiclasserror) { $ClassFound = 0 } else { $ClassFound = 1 }

$ClassFound


Obtaining Warranty Information (currently HP only)

If you do a Google search for any combination of script, warranty information, powershell, vb etc you'll find loads of posts with examples.  For HP unfortunately, all the posts I found had links for warranty lookup that no longer worked, either due to HP removing the link or redesigning their websites. It proved to be quite difficult to track down a working weblink, but I finally managed to work one out for desktop machines at least (have yet to work out or find a direct link that can be used for server kit)

The script below is specifically for HP kit but other links may/will exist for other manufacturers. The script reads the SQL table directly from SCCM for all devices with missing warranty information, scrapes the webpage for the relevant information, then stores the returned information in CSV files for later use.

#Get the relevant records directly from SQL for any reported devices with no warranty information
$SQLSelect = "SELECT ass.ResourceID, ass.Name0, ass.Model0, ass.Domain0, ass.Manufacturer0, war.SerialNumber0,
war.ProductNumber0, war.WarrantyInfo0, war.WarrantyDate0
FROM v_GS_Computer_System ass
INNER JOIN v_R_System sys on ass.ResourceID=sys.resourceID
INNER JOIN v_GS_PC_BIOS bios ON ass.ResourceID = bios.ResourceID
INNER JOIN v_GS_WARRANTYDETAILS war ON ass.ResourceID = war.ResourceID
WHERE ass.Manufacturer0 NOT LIKE 'VMWare%' and war.WarrantyInfo0 is null
AND sys.client0=1 AND sys.obsolete0=0 AND sys.Active0=1"

#SQL Server connection information
$SQLServer = "xxxxxxxx" # Name of SCCM SQL server (usually the CAS, or primary if only 1 primary)
$SQLDatabase = "CM_xxx" # Name of database with site code
$SQLAuth = "uid=xxxxxxxx;pwd=xxxxxxxx" # A SQL account with at least R/O access



$SQLConnection = New-Object System.Data.SqlClient.SqlConnection
$SQLConnection.ConnectionString="Server=$SQLServer;Database=$SQLDatabase;$SQLAuth"
$SQLConnection.Open()

$SQLCmd = New-Object System.Data.SqlClient.SqlCommand
$SQLCmd.CommandText = $SQLSelect
$SQLCmd.Connection  = $SQLConnection

$SQLAdapter = New-Object System.Data.SqlClient.SqlDataAdapter $SQLCmd
$SQLDataset = New-Object System.Data.DataSet


$SQLAdapter.Fill($SQLDataset) | Out-Null

if ($SQLDataset -ne $null)
{
    $ComputerList = $SQLDataset.Tables[0]

    $RowCount = 1

    $ComputerList | % {
        $ComputerName = $_.Name0
        $sSerialNumber = $_.SerialNumber0
        $sProductNumber = $_.ProductNumber0
        $sManufacturer = $_.Manufacturer0

        $Rows = ([array]($ComputerList)).length

        Write-Host "Processing Row $RowCount of $Rows...Checking $ComputerName..." -NoNewline
        $RowCount++

        switch ($sManufacturer)
        {
            "HP" {
                $sWebLink = "http://h10025.www1.hp.com/ewfrf/wc/weResults?cc=us&dlc=en&lc=en&tmp_weCountry=gb&X-view=mobile&tmp_weCountry=gb&tmp_weSerial=$sSerialNumber&tmp_weProduct=$sProductNumber&product=&lc=en&dlc=en&cc=us&tmp_weDest=&tmp_track_link=ot_we%2Fsubmit%2Fen_us%2Fentitlement%2Floc%3A0"
            }
            "Hewlett-Packard" {
                $sWebLink = "http://h10025.www1.hp.com/ewfrf/wc/weResults?cc=us&dlc=en&lc=en&tmp_weCountry=gb&X-view=mobile&tmp_weCountry=gb&tmp_weSerial=$sSerialNumber&tmp_weProduct=$sProductNumber&product=&lc=en&dlc=en&cc=us&tmp_weDest=&tmp_track_link=ot_we/submit/en_us/entitlement/loc:0"
            }
        }

        try
        {
            $OutputFile = ".\$ComputerName.csv"

            if (Test-Path $OutputFile)
            {
                Write-Host "File already exists..."
            }
            else
            {
                $webClient = new-object System.Net.WebClient
                $output = ($webClient.DownloadString($sWebLink)).tolower()

                $WarrantyInfo = ($output.Substring($output.IndexOf("warranty status"),250))
                $WarrantyDate = ($output.Substring($output.IndexOf("warranty end date"),250))

                if ($WarrantyInfo -match "warranty has expired") { $Warranty = "Expired" }
                if ($WarrantyInfo -match "covered under warranty") { $Warranty = "Covered under warranty" }

                $WarrantyDateFound = [regex]::Match($WarrantyDate,"[0-9]{4}-[0-9]{2}-[0-9]{2}").Groups[0].value

                write-host "$ComputerName, Warranty [$Warranty], Warranty End Date [$WarrantyDateFound]" -NoNewline

                $ComputerInfo = "" | select ComputerName, SerialNumber, ProductCode, WarrantyInfo, WarrantyDate

                $ComputerInfo.ComputerName = $ComputerName
                $ComputerInfo.SerialNumber = $sSerialNumber
                $ComputerInfo.ProductCode = $sProductNumber
                $ComputerInfo.WarrantyInfo = $Warranty
                $ComputerInfo.WarrantyDate = $WarrantyDateFound

                if (Test-Path $OutputFile) { Remove-Item $OutputFile -Force }

                Write-Host "Writing file for $ComputerName..."

                $ComputerInfo | Export-Csv $OutputFile -NoClobber -NoTypeInformation
            }
        }
        catch
        {
        }
    }
}
The CSV files that are output contain warranty information for each device.


Other weblinks i've come across on google searches re other manufacturers (NOTE i've NOT tested these as I have none of these devices to test!  Feel free to try them out)

Dell : http://support.dell.com/support/topics/global.aspx/support/my_systems_info/details?servicetag=' + (Machine Serial Number)

IBM / Lenovo :  http://www-307.ibm.com/pc/support/site.wss/warrantyLookup.do?type=' + LEFT (Machine Model, 4) + '&serial=' + (Machine Serial Number) + '&country=897'

Acer : http://secure3.tx.acer.com/FindSystem/findsystem.aspx?Title=Information&sn=' + (Machine Serial Number)

I'll cover reading these files back and storing the information back on each device's custom class in a later post.

1 comment:

  1. Hi..

    Thanks for this - just one small correction.

    I had to add the following line:
    $ComputerName = $env:computername

    ReplyDelete