Thursday, January 29, 2015

Using SCCM 2012 Compliance Settings to Determine Hard Drive Health

As long as your computer has S.M.A.R.T hard drive diagnostic capabilities, the following can be used to track hard drive failures.

Configuration Item(s) in SCCM 2012.

Option 1 - Using WQL query

Name - Hard Drive Predictive Failure
Platforms - All (Although, if they are virtual machines this will not work.)

Settings -
  • Name: Storage Driver Failure Prediction
  • Type: WQL Query
  • Data: String
  • Namespace: root\wmi
  • Class: MSStorageDriver_FailurePredictStatus
  • Property:PredictFailure
Compliance Rules
  • Name: Possible Hard Drive Failure is True
    • I named it this to remind me that "False" is the result we want.
  • Rule: Storage Driver Failure Prediction Equals False
  • Noncompliance severity: Critical

 Option 2 - Using PowerShell script to read system event log

This option will read the System event log and count any 'disk' source logs that are not Information level. 
Note: This will include issues with temporarily attached external hard drives or USB drives.

Name - Event Log Disk Errors
Platforms - All (This will work for servers and virtual machines)
  • Name: Report disk errors found in Event Log
  • Type: Script
  • Discovery script (See end of post)
    • Counts the events and writes that value.
Compliance Rules
  • Name: Disk error count
  • Rule: Less than 1 (That's a number one)
  • Noncompliance severity: Critical
Now that you have created the Configuration Items, you can add (one or both) to a Configuration Baseline and deploy them to your collections.

Once deployed create collections for the non compliant systems and then use that information in reports for your help desk or create a Task sequence that alerts the end user that the hard drive is may be failing.

Here's the PowerShell script...
- Updated Feb 3, 2015 to exclude '*Device\Harddisk1\DR1*' event logs.

#Version 2.30 Feb 3, 2015
#Designed for SCCM Baseline
$AllEvents = 0

#Default Event Logs
$Provider = "disk"
$HourChange = 24 #Up to you how far back you want to go
$TimeNow = [DateTime]::Now
$TimeChange = [DateTime]::Now.AddHours(-$HourChange)

#Check Event Log for errors
$EventLogNames = "System"

ForEach ($log in $EventLogNames){
    $entry = " "
    #Search Event Logs
    $LogEntry = Get-WinEvent -LogName $log | Where-Object {$_.timeCreated -ge $TimeChange -and $_.ProviderName -contains $Provider -and ($_.LevelDisplayName -eq 'Warning' -or $_.LevelDisplayName -eq 'Error' -or $_.LevelDisplayName -eq 'Critical')}
        ForEach ($entry in $LogEntry){
            $EvLevel = "Level: `t" + $entry.LevelDisplayName + $nl
            $EvEventID = "EventID: `t" + $entry.ID + $nl
            $EvMessage = "Message: `t" + $entry.Message + $nl
            $EvSource = "Source: `t" + $entry.ProviderName + $nl
            $EvTime = "Time Created: `t" + $entry.TimeCreated + $nl
            #write-host $EvLevel + $EvEventID + $EvMessage + $EvSource +$EvTime + $nl

            #If ($entry.LevelDisplayName -eq "Critical" -or $entry.LevelDisplayName -eq "Warning" -or $entry.LevelDisplayName -eq "Error"){
            If ($EvMessage.tostring() -like '*Device\Harddisk1\DR1*'){
            ElseIf ($entry.LevelDisplayName -eq "Critical" -or $entry.LevelDisplayName -eq "Warning" -or $entry.LevelDisplayName -eq "Error"){
             $AllEvents += 1

write-host $AllEvents

More SCCM related posts