How to use the SCL debugger
- Ivaylo Fiziev
- 5 hours ago
- 6 min read

I've never done a post related to how the SCL debugger is meant to be used. Here it is - following some recent questions from colleagues.
You can imagine the SCL debugger as a simplified version of the debugger you have in Visual Studio. It only covers the basics. As you might happen to know Visual Studio works in its own process and attaches to the process running your code when you debug. Usually you pick the process from a list and then select the debug engine (native, managed, script etc.) to use. Once attached you can put breakpoints and examine/modify the state of the code when a breakpoint is hit. What does it mean to attach? It actually means to install a hook into the target process. This hook provides the debugger with the state. Without going into much details - this is how you find logical errors in the code.
SCL debugger follows this same idea. When run it automatically attaches to Process Simulate using the script debug engine from Microsoft. The script debug engine allows the debugger to discover all SCL scripts running in Process Simulate. Then it enumerates the code contexts in each script. Eventually this allows the debugger to put breakpoints and examine/modify its state when a breakpoint is hit. By 'state' I mean the state of the variables.
And here comes the first important thing to understand: The SCL debugger relies on code coming from Microsoft! It is the same code that Visual Studio uses to attach to a process. This code is encapsulated in a component known as the Program Debug Manager (PDM). The PDM is distributed in two ways:
1. As part of the Visual Studio installation - if you have Visual Studio installed the SCL debugger will also work. This is the option to be used by developers.
2. As part of the Remote Tools installation - if you don't have Visual Studio installed you need this package. Here is a link: https://visualstudio.microsoft.com/downloads/?cid=learn-onpage-download-cta#remote-tools-for-visual-studio-2022. Always install the latest one! It is a free package but we don't have the legal right to distribute it. This is the option to be used by customers.
If neither of these is installed you'll get an error when you try to run the SCL script with the debugger enabled. The error message will invite you to install the Remote Tools.

This message will appear in the simulation monitor if you try to run the simulation with the debugger enabled.

You activate the debugger by clicking on the 'bug' button in SCL editor. You should do this for every resource with script that you want to debug.
Provided that you have the prerequisites (PDM) installed the debugger will pop whenever you run the simulation or execute the script from the SCL editor. When it pops you'll notice that is stops at the first statement in the SCL code. This allows you to put breakpoints before the code actually runs. If it does not stop you'll have no chance of debugging at time zero.
At this point you can either trace the code (execute line by line) or resume it (leave it running until a breakpoint is hit). In both cases when the code stops you can use the tool windows (scripts, variables, watch, call stack, commands) of the debugger to examine the state. Here is how it looks:

Lets take a closer look at each of the tool windows:
Scripts

Each resource that has a SCL script is represented as a script application (a root node in the tree). Each script application has a main script - the one you edit in the SCL editor.
In addition the main script can reference a number of sub scripts. Subscripts come from the SCL Vault and are listed under the main one.
The window shows the current script (in bold) and also indicates scripts that have breakpoints in them (red dot). The current script is the script currently on focus. This indication helps you understand the context where the script is used. This is helpful in the case of script sharing between different resources or debugging many script applications at the same time. The breakpoint indication helps you find scripts with breakpoints. When you try to close the debugger all breakpoints should be first removed! You can double click on a script to open it and add/remove breakpoints.
Variables

This window shows the state of the variables within the current script. Basically name, type and value. With arrays and UDTs the value is provided as a JSON string that represents their structure. When these strings get large the button with the magnifying glass can help you visualize them better. This can also be useful when working with large strings.

For now it is a read only list that gets updated on each breakpoint. Values that change between two breakpoint hits are highlighted in red.
Watch

Here you can evaluate expressions related to the current script. The expressions can be of arbitrary complexity. Usually you check the expressions before the next statement is executed. You can also use the watch to focus on a particular variable when the list of variables becomes big. The debugger shows the type and the value after evaluating the expression. You can copy/paste or drag/drop expressions from the code after selecting them with the mouse.

If a function is used in the expression, the function will actually be called! This might have side effects! Use it with caution!
Call Stack

This window shows the sequence of script calls that has lead to the current script. It shows the line number (indirectly the statement) where the script execution is currently on. A click on a script here takes you to the exact place in the code where the call is done. This also changes the current script and therefore updates the scripts, the variables and the watch window.
Commands

This window allows you to examine and change the state of the code by evaluating expressions and executing statements. Usually the assignment statement is used for changing the state but it can be any other statement that affects the state. Expressions are prefixed with a question mark.
Again functions can have side effects if you use them here!
How do you set/remove a breakpoint? You simply click on the margin area of a given line. The statement related to the breakpoint will be highlighted when you set it. If a statement is not available at this line nothing will happen. Breakpoints are indicated with a small circle in the margin area.

Alternatively you can put the mouse cursor on the line and click the related tollbar button or use the hotkey (F9).
What happens when a breakpoint is hit? The short answer is that the execution of the code stops. However not only the script stops. Process Simulate itself stops! It hangs since the script runs synchronously in its main thread. For a developer this is completely expected but for regular users this might be frustrating. This is the second important thing to understand: You cannot use Process Simulate while the script is stopped! Any change that you might expect to see in the graphics will not take place until the script completes.
This behavior is essential for the debugger to work. Imagine trying to examine the state while the code runs. It is like trying to take a look inside a speeding train. You just cannot do it unless you stop the train.
Speaking on stopping the train the breakpoint is not the only option. You can request the code to stop at the next statement as soon as possible. This is known as a debugger halt. This is what the pause button does. It is enabled only while the code is running.

Once the code stops you have the option to resume it (the play button), to stop it completely (the stop button) or to trace it (the step over, step into and step out buttons).
When you trace the code using the 'Step Over' option the statements are executed one at a time. Then you can immediately see the effect of the last statement over the state of the code. 'Step Into' does pretty much the same thing but if the next statement is a script function call it actually enters the function showing you the state inside it. Lastly 'Step Out' exits the script function and stops on the next statement in the calling script.
Runtime errors are reported by the debugger using a popup balloon that points at the problematic statement.

What is a runtime error? It is an error preventing the code from running correctly. An exception of some kind. When such error occurs the debugger allows you to either stop or resume the execution. If you resume the behavior of the script is undefined!
Lastly the debugger can format the values of integral types as either a decimal or hexadecimal literals. If you work with bit masks a hex representation can be beneficial.
These are the basics. Advanced topics like: enabling/disabling breakpoints, conditional breakpoints, listing breakpoints, moving the instruction pointer, searching within the code etc. are not covered yet.




Comments