Capturing SCCM TS logs – The PowerShell way

Ever had a task sequence fail? Wouldn’t it be nice to view the logs from a central location? Then this is the tutorial for you.

There are several posts out there how to capture logs, but they’re all a bit cumbersome for my tastes… involving several additional steps in your task sequences and relying on CMD commands (yuck!).

Here’s how to do it all in a single PowerShell script.

Pre-theory

As you probably know, when a task sequence fails it stops and usually show you this a countdown like this:

So, instead of just stopping when a failure occurs, how do we force the TS to proceed to copy logs instead? Answer lies in taking advantage of the “Continue on error” TS step property:

By nesting the TS under one group, checking its “Continue on error” property and lastly setting the capture log step last in the TS, we make sure logs will always be copied, regardless of outcome.

Now for the script.

The script

For the impatient and experienced, you can skip further down for the full script. Verbose description follows:

First we need to initialize the task sequence environment to an object stored in a variable called $TSEnv.

$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment

Next, let’s store the computer name in the variable $TSComputerName

$TSComputerName = $TSEnv.Value("OSDComputerName")

If OSDComputerName doesn’t exist, we will use _SMSTSMachineName instead.

If (!$TSComputerName) { $TSComputerName = $TSEnv.Value("_SMSTSMachineName") }

Let’s set the TS logpath to a variable.

$TSLogPath = $TSEnv.Value("_SMSTSLogPath")

Now for more involved stuff. For a good organization of your TS logs, it’s preferable to sort them by Success and Failure. How do we determine if a TS was either? The self-explanatory boolean _SMSTSLastActionSucceeded variable tells us! If it’s false, the last step was a failure, if true, all’s ok.

So, our IF statement, in case of TS failure:

If ($TSEnv.Value("_SMSTSLastActionSucceeded") -eq "false")

For better visibility of our later custom error message, it’s best close the TS progress bar. We do this by invoking the TSProgressUI object and calling its CloseProgressDialog method.

(New-Object -COMObject Microsoft.SMS.TSProgressUI).CloseProgressDialog()

At this point, let’s set the central log location we want to write the logs to. We’ll use the computer name as the last folder.

$LogLocation = "\\YourServer\ConfigMgr\Logs\Tasksequence\Failure\$TSComputerName"

Let’s remove old logs for this model, recursively, forcefully and without error (in case previous logs don’t exist).

Remove-Item $LogLocation -Recurse -Force -ErrorAction SilentlyContinue

Let’s then copy the logs!

Copy-Item $TSLogPath $LogLocation -Recurse

Finally, let’s display an error message using WshShell popup method! This method has some possibilities. In this example, we display a popup that will say that an error occurred, log location and prompt the user if the want to shut down the system or continue (and exit the TS). You can read about the syntax more here: https://msdn.microsoft.com/en-us/library/x83z1d9f(v=vs.84).aspx

Start by creating a WshShell object and setting it to the $WshShell variable.

$WshShell = New-Object -ComObject WScript.Shell

Create popup. Insert your text as in the example.

$PopUp = $WshShell.Popup("An error occurred! Check the logs on the server in this location: `n\Logs\Failure\$TSComputerName.`n`nTurn off the computer?",0,"Error occured",0x4 + 0x10 + 0x1000)

It will look like this.

A useful pop-up for once.

Again, I recommend you read the documentation if you want do make further customization to the prompt.

For the next step, we process the input to the prompt. The docs state, an answer of Yes equals Return value of 6, 7 for No. In this case, we only need to do something if the user chose to shut down the system.
Since shutdown.exe is not provided in WinPE, we have to use the command Wpeutil ShutDown instead. As for full OS, we use shutdown.exe, but we use it through the SMSTSPostAction variable instead. SMTSPostAction is basically an optional command line that is run after a TS ends, after TS environment is closed. In this case it’s preferable to shut down that way, ensuring that the TS environment does not end abruptly, possibly causing the client to be stuck in provisioning mode (a hassle!).

If ($PopUP -eq "6") {

    If ($TSEnv.Value("_SMSTSInWinPE") -eq "true") { wpeutil shutdown }
    
    Else { $TSEnv.Value("SMSTSPostAction") = "shutdown /s /t 0 /f" }
}

That’s it for the failure scenario! Next, let’s get dressed for success. Basically we just copy the logs, pretty much like in the failure scenario.
Also, if you want to set a SMSTSPostAction, you can do it here. In this case we have a restart.

Else {

    $LogLocation = "\\ville02\ConfigMgr\Logs\Tasksequence\Success\$TSComputerName"
    Remove-Item $LogLocation -Recurse -Force -ErrorAction SilentlyContinue
    Copy-Item $TSLogPath $LogLocation -Recurse
    $TSEnv.Value("SMSTSPostAction") = "shutdown /r /t 5 /f"
}

Full script

Apply script in TS

Now it’s time to put the script in the TS. Due to SCCM task sequences being executed in Session 0 and user console session being in Session 1, we need some assistance to move execution of the script to the user session to show the prompt.
Enter ServiceUI.exe. ServiceUI.exe is an executable found in MDT (Microsoft Deployment Toolkit) and its purpose is to break out processes from Session 0 into Session 1. You can find the executable in an installed MDT instance. Insert ServiceUI.exe in the same folder as the script.

Anonymous access to network share

For the script to work in both full OS and PE, you need to have the log folders to allow Anonymous write access. To avoid packages, you can also insert the script into a folder where Anonymous has read access.
Here’s a fine guide written by Vitorio Delage how to accomplish this: https://vitoriodelage.wordpress.com/2016/04/07/creating-an-anonymous-smb-network-share/

Script in TS

Finally, insert a “Run command line” step as the last one in the TS. The command line should be:

ServiceUI64.exe -process:TSProgressUI.exe %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File SCCM-CopyLogs.ps1

In the “Start in:” field, add the location of the script. Also check to Disable 64-bit redirection, no need for that.

That’s it!

Leave a Reply

Your email address will not be published. Required fields are marked *