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:
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.
Next click on the Create… button.
Give the rule a name, and set the Message ID to 30196.
On the Actions tab, select the "Run a program" checkbox and configure the command line.
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:
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:
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
001002003004005006007 | # EventID 30196 - Software Updates Deployment CreatedC:\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 ModifiedC:\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
001002003004005006007008009010011012013014015016017018019020021022023024025026027028029030031032033034035036037038039040041042043044045046047048049050051052053054055056057058059060061062063064065066067068069070071 | 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.AssignmentTypeFROM vCI_CIAssignments VCIA INNER JOIN Collections COLS ON COLS.CollectionID = VCIA.TargetCollectionIDINNER JOIN CollectionMemberCounts CMC ON CMC.CollectionID = COLS.COllectionIDINNER JOIN ServerData SRV ON SRV.ID = CMC.SiteNumberWHERE 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)}## |
Comments
- Anonymous
April 03, 2015
In the last blog post the code used was also triggering notifications for Configuration Baselines. EventIDs