Many of you probably know about Status Filter Rules and how you can configure such to run scripts when a certain status message has been sent to the site server. This method is great for e.g. running a script to email a department or person that for instance a task sequence was successfully executed. I’ve used this method before, but I wanted to know if you can determine the execution status of a task sequence by using the SMS Provider and PowerShell also. And it turns out (no big surprise really) that you can!
The scenario I was faced with at one of my customers recently, was to find a way to get a task sequence successful execution status. They were currently using a web service to accomplish this, but after upgrading their environment to ConfigMgr 2012 R2 the web service became unstable and would intermittently not return any data. So my task was to find a stable solution, and I turned to PowerShell for that.
It turns out that there’s a class called SMS_StatusMessage (you’ll find more information about that class here) where the status messages I was looking for could be located. Since this class holds alot of instances, it’s important that you try to run a query as efficient as possible. That’s why I used the -Filter option of Get-WmiObject instead of the Where-Object cmdlet in the scripts you’ll find below.
How to use the script
Since the customer was using Orchestrator together with ConfigMgr to deploy their devices, I had to build a script that would return a specific value if a task sequence for a specific device had successfully completed. I decided to use a variable called $Status to determine if the Orchestrator workflow could continue or not. The script below will check against a specified Primary Site server (or CAS if you have that), assuming that the SMS Provider is installed locally on the server, if a device has successfully completed a task sequence in the past 24 hours. In this case it was not necessary to also specify exactly what task sequence that had successfully been executed, so that’s why that’s not a part of this script. The Status Message ID that we’re using to accomplish this is 11143.
If you’d like to use this in your environment for another purpose, you could simply replace the $Status = 0 part with additional code that suit your needs.
$SiteServer = "<server_name>" $SiteCode = "<site_code>" $ComputerName = "<device_name>" $TimeFrame = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime((Get-Date).AddHours(-24)) $Status = 1 $TSSummary = Get-WmiObject -Namespace "root\SMS\site_$($SiteCode)" -Class SMS_StatusMessage -ComputerName $SiteServer -Filter "(Component like 'Task Sequence Engine') AND (MachineName like '$($ComputerName)' AND (MessageID = 11143))" -ErrorAction Stop $StatusMessageCount = ($TSSummary | Measure-Object).Count if (($TSSummary -ne $null) -and ($StatusMessageCount -eq 1)) { foreach ($Object in $TSSummary) { if (($Object.Time -ge $TimeFrame)) { $Status = 0 } } } elseif (($TSSummary -ne $null) -and ($StatusMessageCount -ge 2)) { foreach ($Object in $TSSummary) { if ($Object.Time -ge $TimeFrame) { $Status = 0 } } } else { $Status = 1 }
Now this may not be useful for a wider range of environments, but perhaps you’d just want to run a PowerShell script from the console, providing some parameters and then get the computer name and execution success time information directly? Then save the script below as e.g. Get-TSExecutionStatusForDevice.ps1.
[CmdletBinding()] param(
[parameter(Mandatory=$true)]
$SiteServer,
[parameter(Mandatory=$true)]
$SiteCode,
[parameter(Mandatory=$true)]
$ComputerName,
[parameter(Mandatory=$true)]
$PastHours ) $TimeFrame = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime((Get-Date).AddHours(-$PastHours)) $TSSummary = Get-WmiObject -Namespace “root\SMS\site_$($SiteCode)” -Class SMS_StatusMessage -ComputerName $SiteServer -Filter “(Component like ‘Task Sequence Engine’) AND (MachineName like ‘$($ComputerName)’ AND (MessageID = 11143))” -ErrorAction Stop $StatusMessageCount = ($TSSummary | Measure-Object).Count if (($TSSummary -ne $null) -and ($StatusMessageCount -eq 1)) { foreach ($Object in $TSSummary) { if (($Object.Time -ge $TimeFrame)) { $PSObject = New-Object -TypeName PSObject -Property @{ SuccessExecutionTime = [System.Management.ManagementDateTimeconverter]::ToDateTime($Object.Time) MachineName = $Object.MachineName } Write-Output $PSObject } } } elseif (($TSSummary -ne $null) -and ($StatusMessageCount -ge 2)) { foreach ($Object in $TSSummary) { if ($Object.Time -ge $TimeFrame) { $PSObject = New-Object -TypeName PSObject -Property @{ SuccessExecutionTime = [System.Management.ManagementDateTimeconverter]::ToDateTime($Object.Time) MachineName = $Object.MachineName } Write-Output $PSObject } } } else { Write-Output “No matches found” }
Run the following command line:
.\Get-TSExecutionStatusForDevice.ps1 -SiteServer CM01 -SiteCode PS1 -ComputerName CL01 -PastHours 24
If a match is found for what you’re searching for, the result will look something like this:
I hope you can put this to good use! If you have any questions, just drop me an email or a comment below.
I am looking for a way to get the name of the completed task sequence as well. can you please guide.