Error Logging in Batch Files and Microsoft System Center Configuration Manager 2012 When Configuration Manager 2012 launches a batch file on a command line (using either an Application, Package or TS Run Command Line) what happens behind the scenes is the executable cmd.exe is launched running each line of the batch file. When Cmd.exe runs it holds the error value from the execution of each line of the batch file in a variable called ERRORLEVEL. Since cmd.exe’s execution of each line of the batch file will not stop if a non-zero return code is returned from a specific line of the batch file, the ERRORLEVEL variable is continually overwritten. When the last line of the batch file is executed, the line's return code will be entered into ERRORLEVEL. At this point (unless cmd.exe is instructed otherwise), cmd.exe will close and return the present ERRORLEVEL as the return code which will be logged in Configuration Manager 2012's log files. In summary, by default only the last line of a batch file will be returned to Configuration Manager 2012. Example of How a Batch Behaves and Reports Errors in Configuration Manager 2012 Let's look at an example of this behavior. Consider a batch file with a single command that has an error such as 'copy' with no parameters Batch file contents: copy When this batch file is run on a client through Software Center (I chose a simple package) the following error will be displayed in Software Center. This is because the copy command returns 1 if there is a bad parameter. Let’s now change the batch file by adding a remark at the end which will always execute successfully. Batch file contents: copy rem This will always work When we redistribute and check the return code in Software Center we see that no error is displayed since the last line was successful. How to Add Logging to Every Line in a Batch File and Report a Failure in Configuration Manager 2012 Now what if we want EVERY line within a batch file logged within Configuration Manager 2012. As with other scripting, a decision will have to be made on what to do when an error is encountered. For this example, I am choosing to stop the batch file and return the error to Configuration Manager 2012 if it is non-zero. NOTE that NOT EVERY command returns a 0 return code when it is successful. Scenarios like rerunning a script and thereby creating a directory that’s already there OR running an .msi that has a reboot pending may return non-zero return codes. It is important to ensure the error logging you put in place acts how you want it to. Now for an example on how to return any non-zero return codes to Configuration Manager 2012 from any line in the batch file. Adding the following line in the batch immediately following the line you want to return will allow you to return a specific error number and exit the batch file. This command will trigger if the error is 1 or greater, then exit with the return code specified. IF ERRORLEVEL 1 EXIT /B <error to return> A simple strategy around using this command to map errors to where they occur within the batch file could be to set them up sequentially and perhaps starting a little higher to highlight that’s they are custom errors. When an error is reported to Configuration Manager 2012, the batch file can then be referenced to see which line failed. For example, a two line batch file might look like: Md c:\temp\test IF ERRORLEVEL 1 EXIT /B 11 Copy “%~dp0test.txt” c:\temp\test /y IF ERRORLEVEL 1 EXIT /B 12 Some command-shell commands like ‘md’ will have non-zero commands if they are rerun. In this case it’s because creating a directory that’s already present generates a non-zero error. A strategy to work around this might be to avoid error logging on lines that react this way if rerunning is a scenario that’s supported. The example batch file would then be as shown: Md c:\temp\test Copy “%~dp0test.txt” c:\temp\test /y IF ERRORLEVEL 1 EXIT /B 11 How to View Errors within Configuration Manager 2012 Moving on to how to check for errors within the Configuration Manager 2012 console and on the client, I’ll cover Configuration Manager 2012 Packages and Task Sequences. Since Configuration Manager 2012 Applications evaluate to true/false based on an assigned criteria this criteria can be used to detect any errors instead of built-in error logging so it will not discussed here. First, let’s make a deliberate error to the batch file we used in the last section. Then distribute a Package containing it and see how the custom error looks in Software Center. Here’s the batch file with the error: Md c:\temp\test Cpy “%~dp0test.txt” c:\temp\test /y IF ERRORLEVEL 1 EXIT /B 11 When this batch file is run on a client through Software Center the following error is displayed in Software Center. Within the Configuration Manager 2012 console this same error can be seen in both the Deployment Monitoring section and within the State Messages. Note to reference the state messages grab the deployment ID from the first picture and put it into the state message query ‘All Status Messages for a Specific Deployment at a Specific Site’. A screenshot of each view is shown below: Moving on to how to monitor custom errors within a task sequence I put together a task sequence that runs the following steps with ‘Continue on Error’ checked for all three: - Runs a package with the same batch file from the last section Runs the same batch file using the TS Run Command Line step referencing a package Since ‘Continue on Error’ is set for both steps the TS will finish regardless and should have custom errors logged in the state messages and smsts.log when the batch file runs in each of the first two steps. Looking at the smsts.log on the client the first two steps report the custom error code as shown below and when executed from the TS run command line step even provide a detail on what the issue was: TS Run Command Line Referencing a Package: On a side note, the next line in the log will attempt to translate the custom error code into the associated Windows error. In this case the description will not be correct since the custom error 11 was arbitrary. It should be possible to leave the native error code from cmd.exe, but then it may be difficult to determine what line the error occurred on. Package: In the case of the package, a hex prefix of 0x80070000 is added to the exit code of 11 creating 0x8007000B which when translated to decimal is the exit code shown of 2147942411. Next, how do we report on these errors within the Configuration Manager 2012 console? Since the Deployment Monitoring section will only tell you that the TS step failed, we’ll need to look at the state messages. Use the same tip we used before to grab the deployment ID from the Deployment Monitoring section and put it into the state message query ‘All Status Messages for a Specific Deployment at a Specific Site’. The screenshots below show the corresponding errors: TS Run Command Line Referencing a Package: Package: That’s all I have for now. If this technique is useful to you I hope this demonstration gave you some ideas on how to implement it. Jim Riekse