I’ve had this post in the queue for a while now and have been working on a script to help with some of this, but with the release of System Center Configuration Manager 1810 I don’t have to hack something together anymore! One of the best new features which allows us to capture the name of the last action using the new variable _SMSTSLastActionName. I’m so excited about this new variable! Let’s get to it.
Failure is Ineveitable
No matter how well you build your ConfigMgr Task Sequences, you will encounter failures. When you are testing in your lab, no big deal, but what about failures at a user’s desk during an In-Place Upgrade? Adding structure to your Task Sequences that can properly handle the failures will add an extra layer of protection against incomplete deployments going unnoticed.
Try – Catch – Finally
If you’ve ever done any programming, you will likely be familiar with concept of Try-Catch-Finally. The general idea is that Try is your block of code. As it executes, if an error occurs, you can allow the code to continue to execute (non-fatal error) or you can Catch the error (fatal-error). In the Catch block, you can execute additional code to process the error. Then, regardless of what else happens, the Finally block will run to process any additonal code that you ALWAYS want to run, no matter the outcome of the previous code. If you structure your Task Sequence using similar logic, you can improve the chances of capturing and remiating failures and reduce the number of failed deployments that make it out into production.
1 2 3 4 5 6 7 8 9 10 11 |
Try { Do Some Thing. Stop (Go to Catch) if there's an error. If no error, skip Catch } Catch { Evaluate the error and take action as needed. } Finally { No matter what happened above, do these steps too. } |
Basic Framework
Inside your Task Sequence, always create a top level group. I like doing this so it’s easier to copy and paste the entire task sequence. Inside this group, create 4 groups at the same level. Main, Failure, Success, Cleanup.
On the Main, Failure and Success groups, check the Continue on error box.
Main
All of your task sequence logic will go into the Main section. If you already have an existing task sequence, you can just add a Run Task Sequence step and reference it! The biggest thing to keep in mind is that you should never enable Contiue on error for any step that is critical or required for a deployment to be considered a success. In fact, if you have a step that occasionally fails, try to add logic to detect whether you need to run the step, before attempting it, just to eliminate any unncessary errors from always showing up in the logs. Additionally, failures fail up the the parent group, so you could have steps fail inside a group, but have the group continue using Continue on error.
As the last step in Main, add:
1 2 3 4 |
Type: Set Task Sequence Variable Name: Set AllStepsSuceeded = True Task Sequence Variable: AllStepsSuceeded Value: True |
By setting this variable, we will know whether we made it to the end without any fatal errors.
Failure
Next, select the Failure group and select Options and add the following Condition: Task Sequence Variable _SMSTSLastActionSucceeded equals False
This will ensure that the Failure group only gets processed if the previous action failed.
Add a Set Dynamic Variables step and set the following:
1 2 3 4 5 6 7 8 9 10 11 |
Variable: FailedStepName Value: %_SMSTSLastActionName% Variable: FailedStepReturnCode Value: %_SMSTSLastActionRetCode% Variable: AllStepsSuceeded Value: False Variable: SMSTSErrorDialogTimeout Value: 86400 |
It’s important that this is the first step that you run after a failed step or else you will lose the values. Now that you’ve captured them, you can process any additional steps that you need to inside the Failure group.
Success
Next, select the Success group and select Options and add the following Condition: Task Sequence Variable AllStepsSucceeded equals True. This will ensure that Success will only run if the task sequence made it to the end without failure. You can add any steps inside here that you would only want to run if the Task Sequence was successful.
Cleanup
Finally, on the Cleanup group, add steps like Copy Logs or Remove from Provisioning Mode or any other steps that will help make it easier to triage failed deployments. No matter what you add here, be sure that the final step is this one:
1 2 3 4 5 6 7 |
Properties Type: Run Command Line Name: %FailedStepName% Command line: cmd.exe /c exit %FailedStepReturnCode% Options Task Sequence Variable: AllStepsSucceeded equals False |
This last step is the one made possible with ConfigMgr 1810. Now, when my Task Sequence fails and the error dialog is still on the screen, it will display the name of the last step that ran before the error occurred using the _SMSTSLastActionName build-in variable.
The result that a user will see (and likely send you a screenshot of) will show the name of the step that caused the failure now, even though you have already processed all of your cleanup steps, like copying logs. At least at my site, this is a HUGE feature that will make triage much simpler.
Summary
If you build a better task sequence, you will build a better deployment experience for your users and your first line workers who have to troubleshoot issues. Next steps to consider would be adding things like splash screens or login blocking policies (lots of great community blogs about these concepts). You could even get fancy and hide the progress dialog box and show a custom one, including the error dialog. There are so many great ways to customize your Task Sequences, I am just really excited about the _SMSTSLastActionName variable!
Download!
I know it’s not much, but you can download the sample Task Sequence here.
6 Comments
Jesse
December 14, 2018 at 2:48 pmBefore I sound like a condescending jerk… I love the information and your entire blog. There is a ton of really good information based on real world experience.
Error handling is already provided by Microsoft when integrating MDT and creating/using an MDT task sequence. It does require that you use the wizard to get the full advantage of MDT, but there is a lot of really good error handling built-in and wouldn’t require creating the error handling from scratch. Now, that does mean integrating MDT with ConfigMgr. There are lots of really good reasons to do the integration, and honestly, until MDT is retired (doesn’t appear to be any time soon), every ConfigMgr environment that uses OSD should integrate MDT.
https://docs.microsoft.com/en-us/windows/deployment/deploy-windows-mdt/create-a-task-sequence-with-configuration-manager-and-mdt
https://docs.microsoft.com/en-us/windows/deployment/deploy-windows-mdt/integrate-configuration-manager-with-mdt
Adam Gross
December 14, 2018 at 4:27 pmFirst, glad you like the blog.
Second, nothing condescending about your statement.
Third, I personally don’t like the MDT TS structure and all of the “bloat” that doesn’t add any value for my environment, so we don’t use anything other than Gather, and even that has a reasonable PowerShell replacement that does a lot of the same things. While an MDT TS May have error handling structure, the main point of my post was to reinforce 2 things – 1) there’s no reason to let the TS fail without proper handling and 2) the _SMSTSLastStepName is new and changes the way that we can provide support to our users and quickly get information about what failed before going into the logs.
Using MDT is great if that works for you and it provides you with the needed structure to capture errors. If that works well enough for someone’s environment, I certainly would discourage its use. It’s just not what I use and I believe many others are in the same boat and needed a refresher on error handling if they weren’t familiar with MDT.
Adam
January 11, 2019 at 3:57 pmMaybe Im missing something but it seems that the _SMSTSLastActionName variable does not get populated until after the Setup Windows and Configuration Manager step. In testing, failing the OSD immediately after partitioning the HDD and anywhere before the Setup Win and CM step, the Custom Error Dialog shows Failed Step Name: “%_SMSTSLastActionName%”. Failed Step Error Code however does populate properly based on the exit code.
Adam Gross
January 11, 2019 at 3:58 pmHave you upgraded SCCM to version 1810? Otherwise the variable doesn’t exist yet.
Adam
January 11, 2019 at 4:02 pmYes running 1810. And if the failure happens after the Setup Win and CM step, it lists the failed step name properly. Using powershell in the active OSD, the getvariable() does not list a _SMSTSLastActionName variable. Is the variable not active in the WinPE maybe; since after Setup Win/CM step its in the main OS.
Adam Gross
January 11, 2019 at 4:14 pmI’ve only done some basic testing – what you see on the blog – at this point. We will be upgrading production to 1810 within the next week and I hope to implement this solution then and may have better info.
One thing to consider – are you installing the latest SCCM client in your TS? I wonder if that could be the issue. Any time I have seen variables display as %variable% it generally means that the variable doesn’t exist. The underscored variable names are readonly as well. You should be able to pause your TS or at least run a dump variables script at various points to see all of the variables listed out.
Also, what PowerShell are you using to check the values?