SCCM Health Check Script Updated: Version 3.5

Written by Tao Yang

I have just updated the SCCM Health Check Script to from version 3.3 to 3.5

Version 3.4 was finished a while back but I never got time to publish it in this blog. I only emailed 3.4 to few people who contacted me from my blog. Now that I’ve updated it again to 3.5, I thought I’ll just publish version 3.5.

What’s Changed Since 3.3?

  1. Added site system name under ‘site systems with issues’ section
  2. Detect site components that are missing heartbeats.
  3. Changed function Validate-DNSRecord to use Win32_ComputerSystem.caption rather than DNSHostname to retrieve computer name as DNSHostName is not available on computers before Windows 2008.

Update Instruction

A new item has been added to the configuration XML (Health-Check.xml):
   <MaxMissingHeartBeatTolerance>
<Hours>24</Hours>
</MaxMissingHeartBeatTolerance>

As the name suggest, the script raises any site systems as problematic if it has not sent heartbeat for over the X number of hours that you configured in XML (in my example, it’s 24 hours).

You may keep the old XML that you have already configured for your environment as long as you add the following lines in the Health-Check.XML:

 

image

You can download version 3.5 HERE.

23 comments on “SCCM Health Check Script Updated: Version 3.5

  1. Pingback: PowerShell Script: SCCM Health Check | Tao Yang's System Management Blog

  2. tao,

    you write some tight code dude. awesome stuff! 🙂

  3. Pingback: SCCM Site Systems and Components Summarizer Reports | Tao Yang's System Management Blog

    • I downloaded and modified the XML according to our infra…but when i run .psi file, i am not seeing any output. Am i doing something wrong

  4. The is a great script. But I get one error when using it.

    You cannot call a method on a null-valued expression

    $FixedServerNALPath = $ServerNALPath.replace <<<< ("\","\\")
    + CategoryInfo : InvalidOperation: (replace:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Any ideas what I might be doing wrong?

    • On your central site SMS provider, could you please run this and email me the result?

      $CentralSiteCode = “”
      Get-WmiObject -Namespace root\sms\site_$CentralSiteCode -query “SELECT * FROM SMS_PackageStatusDistPointsSummarizer WHERE state0” | fl *

  5. Here is the result. Get-WmiObject : Invalid namespace
    At line:2 char:14
    + Get-WmiObject <<<< -Namespace root\sms\site_$CentralSiteCode -query “SELECT * FROM SMS_PackageStatusDistPointsSummarizer WHERE state0" | fl *
    + CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

  6. Hi Tao,

    Thanks for share, but I’m begineer with powershell. So for me execute it .\SCCM-HealthCheck.ps1 in my console Powershell? I have to do it in Central site? please could you check below:

    PS C:\temp\Script health Status\SCCM-Health-Check-v3.5> .\SCCM-HealthCheck.ps1
    File C:\temp\Script health Status\SCCM-Health-Check-v3.5\SCCM-HealthCheck.ps1 cannot be loaded. The file C:\temp\Script
    health Status\SCCM-Health-Check-v3.5\SCCM-HealthCheck.ps1 is not digitally signed. The script will not execute on the
    system. Please see “get-help about_signing” for more details..
    At line:1 char:23
    + .\SCCM-HealthCheck.ps1 <<<<
    + CategoryInfo : NotSpecified: (:) [], PSSecurityException
    + FullyQualifiedErrorId : RuntimeException

    Thanks for help.

    Ulisses

    • Hi Ulisses,

      Your powershell execution policy is blocking script execution. You have to set your powershell execution policy to either RemoteSigned or Unrestricted. Or sign my script with a cert from a trusted CA.
      To change execution policy. run Set-ExecutionPolicy RemoteSigned -force

  7. I configured the sending email option but it is not working with me !

    is there any tips ?

    Warm Regards

  8. Hi,

    Does this work with SCCM 2012?

  9. I am trying to run the script on Win7 using Powershell 3.0. I get the following error:

    Exception calling “LoadFile” with “1” argument(s): “An attempt was made to load an assembly from a network location which
    would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET
    Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the
    assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for more
    information.”

    At C:\SCCM-Health-Check-v3.5\SCCM-HealthCheck.ps1:1087 char:1
    + [System.Reflection.Assembly]::LoadFile(“$DNSDll”) #| Out-Null

    I have added the powershell.exe.config with the line but still get the error.

    Any suggestions?

  10. Wow – excellent script! Just testing it now, works well after tweaking except for one thing – in PS window, get:

    –Checking SQL logs for errors…
    You cannot call a method on a null-valued expression.
    At C:\temp\SCCM-Health-Check-v3.5\SCCM-HealthCheck.ps1:690 char:36
    + $SQLServiceName = $regKey.GetValue <<<< ("Service Name")
    + CategoryInfo : InvalidOperation: (GetValue:String) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    What do you think is going on?

    • Looks like this msg is spawned because of the logic surrounding the architecture check – the 32-bit registry path is where the required reg key is populated (this is SCCM 2012, BTW), while the architecture check apepars to return a 64-bit build.

      As a test in my test environment, I added the “Service Name” key in the 64-bit registry patch and the error no longer occurs….

  11. Thanks Robinson. Can you tell where exactly I need to add it. If you don’t mind or else could you please share your .PS1 file.

  12. First of all thanks for this wonderful script, I was using this for SCCM 2012 and disabled a few of functions as per my requirement. I added the following function to check the database replication status and include that in the report.

    Also added a new field in XML to skip a few specific DPs and the following code snippet in package distribution related function.

    —————
    $SkippedDPs = @()
    $SkippedDPs += $xml.Configuration.Skip.DistributionPoint
    $arrSkippedDPs = New-Object System.Collections.ArrayList
    foreach ($item in $SkippedDPs) {$arrSkippedDPs.Add(($item.ToUpper())) | Out-Null}
    Write-Host “The following DPs will be skipped:” -ForegroundColor Green
    Write-Host $arrSkippedDPs -ForegroundColor Green
    —————————–

    foreach($dp in $arrSkippedDPs)
    {
    $arrAllPackagesWithIssues =$arrAllPackagesWithIssues | ?{$_.PkgServer -inotmatch $dp} # | select PackageID,PkgServer
    }
    ———————————-

    Function Check-SiteLinkStatuses ($CentralSiteCode, $CentralSiteProvider, $arrSkippedSites)
    {
    Set-Location “$($CentralSiteCode):”
    $arrSiteLinkSummarizer = @()
    $objSitesWithLinkIssues = Get-CMDataBaseReplicationStatus #| Where-Object{$_.LinkStatus -ne 2 -OR $_.Site1Status -ne 125 -OR $_.GlobalInitPercentage -ne “100%”}
    if ($objSitesWithLinkIssues -ne $null)
    {
    Foreach ($linkStatus in $objSitesWithLinkIssues)
    {
    $SiteCode = $linkStatus.Site2.ToUpper()
    if (!($arrSkippedSites.contains($SiteCode)))
    {
    switch ($linkStatus.LinkStatus)
    {
    2 {$strState = “HEALTHY”}
    default {$strState = “UNKNOWN”}
    }
    switch ($linkStatus.Site2Status)
    {
    125 {$SiteStatus = “ACTIVE”}
    120 {$SiteStatus = “MAINTANCE_MODE”}
    default {$strState = “NEEDS_ATTENTION”}
    }

    $objSiteLinkStatus = New-Object psobject
    Add-Member -InputObject $objSiteLinkStatus -MemberType NoteProperty -Name SiteCode -Value $linkStatus.Site2
    Add-Member -InputObject $objSiteLinkStatus -MemberType NoteProperty -Name SiteStatus -Value $SiteStatus
    Add-Member -InputObject $objSiteLinkStatus -MemberType NoteProperty -Name State -Value $strState

    $arrSiteLinkSummarizer += $objSiteLinkStatus
    }
    }
    }

    if($objSitesWithLinkIssues){Remove-Variable $objSitesWithLinkIssues};
    Return ,$arrSiteLinkSummarizer
    }
    ——————————–
    Also I noticed that substring function was giving an out of range error for the 23 you had used, I added a if to get rid of the error.

    if($package.location.length -gt 23)
    {
    Add-Member -InputObject $objPkgStatus -membertype noteproperty -name PackageLocation -value $($package.Location.substring(23,$package.location.length-23))
    }
    else
    {
    Add-Member -InputObject $objPkgStatus -membertype noteproperty -name PackageLocation -value “Could not determine”
    }

  13. Hi Tao

    Im getting the Exception calling LoadFile with 1 arguements error. An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in preious version of the .NET Framework. Use the ..loadfrom remotesources. I did the

    But still not working.

  14. Hi All,
    I get some errors like this:

    Get-WmiObject : Generic failure
    At C:\SCCM-Health-Check-v3.5\SCCM-HealthCheck.ps1:821 char:16
    + $SQLServers = Get-WmiObject -Namespace root\sms\site_$CentralSiteCode SMS_Syste …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException
    + FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

    Has anybody a fix for that?

    Thanks!
    Regards

Leave a Reply