Skip to main content

ConfigMgr RefreshServerComplianceState as a Configuration Item

State messages are great, because they are quickly processed.  However, it can (and does) occasionally happen where for network reasons, corrupt data, or other influences, some State Messages from your ConfigMgr Clients never make it from the client into your database.  Normally, that isn't a big deal--however, what does sometimes happen is those state messages are for Software Updates.  If you have people who look at reports for Software Updates, and some clients locally say they are Compliant for Software Update KB123456, but when you look at reports based on your database, for that same client, the database says KB123456 on that client is non-Compliant.  Read this: https://blogs.msdn.microsoft.com/steverac/2011/01/07/sccm-state-messagingin-depth/ for a much better explanation of why and how; but the short conclusion to that situation is you want to ask your clients to occasionally run what is referred to as a "RefreshServerComplianceState" locally.  Basically, you are asking your clients to resend the state messages about compliant/non-compliant for all existing Software Updates they are aware of locally, to ConfigMgr, your database.  aka.. exactly what it says on the tin.  Refresh Server Compliance State.

The short and sweet is that it's really just a line or two of vbscript or powershell code.  But if you are in a large environment, you often don't want to tell every single client to all send up state messages all on the same day.  It could POTENTIALLY be a lot of data, and backlog your servers' SQL processing.  It would eventually catch up... but why create a headache for yourself?

Below is a Powershell Script that you COULD choose to run... as a set-it-and-forget-it type of thing.  As-is, if you took the below and deployed it as a Powershell Script in a Configuration Item, and the Baseline were to run daily, your clients would around about 2x a year or so randomly decide to RefreshServerComplianceState .  If you want it more frequent; change the 180 to say... 90  (to be about every 3 months, or 60 to be about every 2 months). 

The below is just a suggestion, and you can take it and break it as you like.

<#
.SYNOPSIS
  This routine is to generate a random number between 1 and "MaximumRandom". In general, it a Maximum Random
  number will likely be 180; if the Configuration Item is run daily, approximately twice a year it is expected
  that a client will randomly pick a value of 1, and trigger a RefreshServercomplianceState
.DESCRIPTION
  - This script would likely be used by a Configuration Manager Administrator as a 'Configuration Item', as the
    "Detection" script in that Configuration Item. The Administrator would set it up as a detect-only script, where
    the "what means compliant" is that any value at all is returned.
  - The Configuration Manager Administrator would likely add this to a baseline, and deploy that baseline to run
    on a Daily basis to their windows-os based devices, which scan for or deploy patches using the Software Updates Feature.
  - Using the MaximumRandom number of 180, presuming the baseline runs daily, approximately twice a year based on
    random probabilities, a client will trigger to run the "ResetServerComplianceState". See the blow mentioned
    below for why this is something a Configuration Manager Administrator might want to do this.
  - If the Configuration Manager Administrator wants to make it randomly occur more frequently or less frequently,
    they would either adjust the $MaximumRandom number higher or lower, or modify the frequency of the Baseline evaluation
    schedule.
  - For interactive testing, modify $VerbosePreference to 'Continue' to see what action was taken. Remember to change
    it back to SilentlyContinue for live deployments.
  - If a client does trigger, an EventLog entry in the ApplicationLog with an Information EventId of 555 from SyncStateScript
    will be created. You can add or modify the -Message entry for the EventLog to be as verbose as you need it to be for
    your own potential future tracking purposes. Perhaps you might want to add in specifics like "Configuration Item
    Named <whatever> in the Baseline <whatever> triggered this action, this was originally deployed on <Date>"

   Credits: Garth Jones for the idea.

   https://blogs.msdn.microsoft.com/steverac/2011/01/07/sccm-state-messagingin-depth
   for the reasons why it's a good idea to do so occasionally.
.NOTES
  2018-05-06 Sherry Kissinger

  $VerbosePreference options are
   'Continue' (show the messages)
   'SilentlyContinue' (do not show the message, this is the default if not set at all)
   'Stop' Show the message and halt (use for debugging)
   'Inquire' Prompt the user if ok to continue
#>

Param (
  $VerbosePreference = 'SilentlyContinue',
  $ErrorActionPreference = 'SilentlyContinue',
  $MaximumRandom = 180,
  $ValueExpected = 1
  #ValueExpected Will likely always be 1, and never change; set as a parameter for ease of reporting.
)

$RandomValue = Get-Random -Maximum $MaximumRandom -Minimum 1
if ($RandomValue -eq $ValueExpected ) {
  Write-Verbose "Random generated value of $RandomValue equals $ValueExpected, therefore RefreshServerComplianceState for ConfigMgr Client State Messages for Updates will be triggered."
  $SCCMUpdatesStore = New-Object -ComObject Microsoft.CCM.UpdatesStore
  $SCCMUpdatesStore.RefreshServerComplianceState()
  New-EventLog -LogName Application -Source SyncStateScript -ErrorAction SilentlyContinue
  Write-EventLog -LogName Application -Source SyncStateScript -EventId 555 -EntryType Information -Message "Configuration Manager RefreshServerComplianceState Triggered to Run. If questions on what this is for, refer to   https://blogs.msdn.microsoft.com/steverac/2011/01/07/sccm-state-messagingin-depth/ "
}

else

{
  Write-Verbose "Random generated value was $RandomValue, which does not equal $ValueExpected, RefreshServerComplianceState for ConfigMgr Client State Messages for Updates was not triggered. "
}

Write-Host 'Compliant' 

CMCB

  • Created on .