Software Updates Deployments – Getting Notified Before It Is Too Late

Overview: Set up Status Filter Rules to log extra information in the Application Event Log and optionally send an email.  Being proactively notified of deployments can be crucial in the rare event that someone targeted a wrong collection or set the deployment for the wrong time.

Scenario:

Suppose you had a Software Updates deployment that went out and the admin mistakenly sent it to a very large collection.  Upon hearing that machines were rebooting unexpectedly, the admin (incorrectly) deletes the Software Update deployment.  The damage is done, and now there’s no information about what/where/when for the deployment.  You’re left staring at an AssignmentID in the status messages that no longer exists.

What to do:

Looking at the Status Message Viewer in SCCM, we get minimal information about the deployment:

Status Message

This really doesn’t tell us the impact of what was deployed, and in the scenario at this point, the information about the deployment is gone.  In order to see more information about this deployment, we need to get information immediately when things are created by using a Status Filter Rule.  The script at the bottom of this post has the query.  Save this to each of your site servers and modify the user config section appropriately.  Next, create a Status Filter Rule at each of your sites.  In the SCCM console navigate to Administration / Site Configuration / Sites.  Right-click the site and select Status Filter Rules.

Filter Rule

Next click on the Create… button.

Create Filter Rule

Give the rule a name, and set the Message ID to 30196.

Filter Rule General

On the Actions tab, select the “Run a program” checkbox and configure the command line.

Filter Rule Actions

The command lines for each Event ID are provided at the end of this post.

Repeat the above process and create another Status Filter Rule for 30197.

Save the script (posted below as well) to a location on each of your site servers, modify the user config and optionally uncomment the last few lines if you have the ability to send email.  Make sure that you replace the location of script in the above command line.  The script is made to be used for both 30196 (creation) and 30197 (modification) Event IDs, so just make sure the command line reflects that for each Status Filter Rule.

Now you’ll have extra information in the Application Event Log on your site server that will give you the following:

Event Log

Modifications, cleanup, and some logic should definitely be added for your environments.  You could, for instance, only log the info and send the email if the deployment targeted All Systems, or had a client count above some threshold that you’d like to know about.  Alternatively, you could use Operations Manager to create alerting based off of the Event ID in the Application Log.

If there are any issues with the information not appearing, you can check the statmgr.log file on your site server to see that the program is correctly firing and its exit status:

statmgr log

spawned process

PowerShell script that is used is posted below.

EDITED 2015-04-03 – Code modification to only include Software Update Deployments.  See next post for details.

DISCLAIMER: The information on this site is provided “AS IS” with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation.  Please test any/all information here in a test environment before running on a production network.

Event ID Run Programs – View on GitHub Gist

001
002
003
004
005
006
007
# EventID 30196 – Software Updates Deployment Created
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -NoProfile -File “C:\Path\To\ScriptName.ps1” -msgID 30196 -AssignmentID %msgis02
 
# EventID 30197 – Software Updates Deployment Modified
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -NoProfile -File “C:\Path\To\ScriptName.ps1” -msgID 30197 -AssignmentID %msgis02
#
#

SCCM_Software_Update_Events.ps1 – View on GitHub Gist

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
param($msgID, $AssignmentID)
trap { $_ | Out-File -FilePath C:\TEMP\sccm_scripting_error.txt -Force }
## USER CONFIG ##############################################
#$email_to = “joe@northwinds.local”
#$email_from = “noreply@northwinds.local”
#$email_server = “192.168.1.1”
# SQL\SERVERNAME\INSTANCE\Databases\DATABASENAME
$sqlString = “SQL\SCCMCAS\DEFAULT\Databases\CM_CAS”
#############################################################
 
New-EventLog -LogName Application -Source “SMS Scripting” -ErrorAction SilentlyContinue
 
Import-Module SQLPS
 
Set-Location $sqlString
 
$query = Invoke-Sqlcmd -Query “SELECT VCIA.AssignmentId, VCIA.AssignmentName, VCIA.UseGMTTimes, VCIA.CreationTime,
VCIA.LastModifiedBy, VCIA.LastModificationTime, VCIA.StartTime, VCIA.EnforcementDeadline,
VCIA.SourceSite, COLS.CollectionName, SRV.SiteCode, CMC.AssignedCount, VCIA.AssignmentType
FROM vCI_CIAssignments VCIA INNER JOIN Collections COLS ON COLS.CollectionID = VCIA.TargetCollectionID
INNER JOIN CollectionMemberCounts CMC ON CMC.CollectionID = COLS.COllectionID
INNER JOIN ServerData SRV ON SRV.ID = CMC.SiteNumber
WHERE VCIA.AssignmentID = $AssignmentID;”

 
$info = “”
if($query[0].AssignmentId -eq $AssignmentID) { $info = $query[0] } else { $info = $query }
if($info.AssignmentType -eq 5)
{
    $totalCount = 0
    foreach($rec in $query) { $totalCount += $rec.AssignedCount }
 
    $message = “”
    switch($msgID)
    {
        30196 { $message = “Updates Deployment CREATED on ‘$($info.CollectionName)’ targeting $totalCount machine(s).`r`n`r`n” }
        30197 { $message = “Updates Deployment MODIFIED on ‘$($info.CollectionName)’ targeting $totalCount machine(s).`r`n`r`n” }
        Default { $message = “Unhandled msgID was passed.” }
    }
 
    $message += “AssignmentID: $($info.AssignmentID)`r`n”
    $message += “AssignmentName: $($info.AssignmentName)`r`n”
    $message += “CreationTime: $($info.CreationTime)`r`n”
    $message += “LastModifiedBy: $($info.LastModifiedBy)`r`n”
    $message += “LastModificaitonTime: $($info.LastModificationTime)`r`n”
    $message += “StartTime: $($info.StartTime)”
    if($info.UseGMTTimes) { $message += ” UTC” }
    $message += “`r`n”
    if($info.EnforcementDeadline.ToString().Trim() -eq “”)
    {
        $message += “EnforcementDeadLine: (None – Available Deployment)`r`n”
    } else {
        $message += “EnforcementDeadLine: $($info.EnforcementDeadline)”
        if($info.UseGMTTimes) { $message += ” UTC” }
        $message += “`r`n”
    }
    $message += “CollectionName: $($info.CollectionName)`r`n”
    foreach($rec in $query) { $message += “$($rec.SiteCode) AssignedCount: $($rec.AssignedCount)`r`n” }
    $message += “TotalCount: $totalCount`r`n”
 
    Write-EventLog -LogName Application -Source “SMS Scripting” -EntryType Information -EventId $msgID -Message $message
 
    #$email = New-Object System.Net.Mail.MailMessage
    #$email.To.Add($email_to)
    #$email.From = $email_from
    #$email.Subject = “SCCM 2012 | $($info.SourceSite) Updates Deployment | $totalCount Targets”
    #$email.Body = $message
    #$smtp = New-Object System.Net.Mail.SmtpClient $email_server
    #$smtp.Send($email)
}
#
#