Program¶
The Program block lets you integrate any program or script into your workflow, provided that it supports command-line execution and file-based input and output (batch mode). The block automates program launches and handles file transfers between your storage in pSeven Enterprise, the program, and other blocks in the workflow. It's often used with Text blocks set up to generate input files for the integrated program and parse its output files.
Getting started¶
The Program block is commonly used to run Windows software installed on an extension node - a workstation or server connected to pSeven Enterprise over the network. To set up the block, you'll need:
- The network name of the computer where your software is installed. This computer will be the run host for both the block and the software.
- The command that launches your software, tested and verified to work from the default system command prompt on the run host.
- Access to the run host and a user account there, so you can test commands locally and gather troubleshooting information if errors occur.
There are three main setup scenarios with this block:
- Many programs accept paths to input and output files as command line arguments. If this is your case, you can use special command line syntax with port names in place of paths. See General program launch.
- If you are running engineering software that works with a project folder and requires a certain project location and structure, see Running engineering software.
- If you are already using batch scripts to run your programs, see Running scripts.
Linux software
The block can run Linux software, but this software must be installed on every node of the Kubernetes cluster where pSeven Enterprise is deployed. Ask your admin whether this is possible in your deployment.
By default, there is no software on the cluster nodes except system packages and Python provided by pSeven Enterprise. Technically you can run Python scripts with the Program block - however, in most cases the Python script block is more practical for this.
General program launch¶
This section provides a basic setup example for a program that accepts paths to its working files and folders as command line arguments or options. A basic example of such a command line is:
thetool -i "D:\Work\input.dat" -o "D:\Work\result.dat"
where thetool is the name of the program executable,
-i and -o are options that specify the input and output paths.
Depending on how your software is installed, running it might require a full path,
such as "C:\Programs\The Tool\thetool.exe" instead of just thetool.
Given this example command, general steps to set up the block are:
- Test running the software locally on the run host, using normal input files. Make sure your commands complete without errors and produce expected results.
- Select a Program block in your workflow to view its settings in the Block properties pane. Program blocks are entirely configured in this pane; opening the block just displays its configuration overview.
- At the top of the Block properties pane, under "Run on:", select the run host.
-
Add an input file to the block configuration:
- Click next to the Inputs header in Block properties and choose Input file from the drop-down menu.
- In the Add an input file dialog, enter the alias you want to use for this file - for instance,
settings file. This is not the file name; it's how you reference this file in your configuration, in particular the command on theRuninput port. - Click OK in the dialog.
A new input port
Input files.settings fileappears in Inputs. You'll pass program input files to this port.
-
Add a result file: click in Inputs, choose Result file, enter its alias:
output file. These ports appear:- Input:
Result files.output file. Sets where to save this file in the workflow results (in the workflow run directory). - Input:
Result files.output file.Take from. Leave unset because you'll reference the file as${output file}in the command. This setting is used for programs that don't accept output file paths as arguments. - Output:
Result files.output file. Outputs the file so you can send it to other blocks.
- Input:
-
On the
Runinput port, enter the same command you've used locally, replacing file paths with${...}aliases:thetool -i "${settings file}" -o "${output file}"For files and folders, always quote the
${...}aliases in the command. The paths they resolve to can contain spaces, and an unquoted path with spaces would be split into separate arguments by the command interpreter. -
Set the
Input files.settings fileport:- select an existing file from your storage, or
- link this port to an output of another block - for instance,
the
Output fileport of a Text block that generates input files.
-
Link the
Result files.output fileoutput port to a downstream block that processes the program output - for instance, to theInput fileport of another Text block that parses output files. -
If you want to save a copy of the output file in workflow run results, set the save location on the
Result files.output fileinput port. Choose a location inside the workflow run directory - the block cannot write any files outside it.Allowed save locations for output files
Blocks cannot write files outside the current workflow run directory. It is recommended that you keep the default file location in the file dialog ("Block working directory") and only change the path. Another allowed location is "Workflow or run" with a relative path - with such settings, the block will save the file to the run directory root.
When the block runs, it creates a temporary remote working folder on the run host, copies all input files there, and launches your program with that folder as the current working directory. Once the program exits, the block collects result files and copies them to the current workflow run directory, then outputs their storage paths to ports.
This is a basic example; for full details about program launch on the run host and related settings, see How it runs.
Running engineering software¶
This section provides a basic setup example for engineering software that works with a project folder.
The scenario has a typical pattern: you maintain a project template,
update one or more files before each run, and collect specific result files afterwards.
Engineering software often doesn't support command line arguments for input and output files,
or requires all paths relative to the project folder -
so you can't use ${file} aliases as in the general program scenario.
Instead, you'll use ports that set input and output file locations as relative paths in the project folder.
To start, you'll need the basic setup information and a project to use as a template. That project must be portable (self-contained): it cannot reference files outside the project folder, and cannot use absolute file paths in any of its settings. Think of it as a project you could copy to another workstation and run there without changes. This is a prerequisite: if your project has hardcoded absolute paths or external dependencies, make it portable first.
A generic example of the project launch command is:
"C:\Programs\ACME\solver.exe" -B -F model.apj -R user_files\journal.ajn
For example purposes, assume that:
model.apjis the main project file,user_files\journal.ajnis a journal script that configures the solver run,- the workflow contains a Text block, which generates a new
journal.ajnfor each run, updating it with new parameter values from workflow inputs, - the solver writes evaluated designs to CSV files in the project folder.
Given this example, general steps to set up the block are:
- Select a Program block in your workflow to view its settings in the Block properties pane. Program blocks are entirely configured in this pane; opening the block just displays its configuration overview.
- At the top of the Block properties pane, under "Run on:", select the run host.
- Upload your project template to the workflow folder or another location in your pSeven Enterprise storage.
- On the
Remote working folder.Prototypeinput port, select the uploaded folder. The block will copy its contents into the remote working folder before running your software. This will be the starting state of your project on the block's run host. -
If your template project is large and only a subset of files needs to travel to the run host, set
Remote working folder.Prototype maskto filter by extension or name. For example, set*.a??on this port to copy only the main project files with.apjand.ajnextensions.If you need multiple masks, open the Edit value dialog on this port and switch the type at the top left to List of masks. Add as many masks to the list as you need.
Example masks
*.dat- all files with the.datextension in the folder root; doesn't match files in subfolders**\*.dat- same, but also matches.datfiles in all subfoldersuser-??- folders nameduser-01,user-02, and so onparams-??.*- files with any extension namedparams-01,params-02, and so on
-
Add the journal file as an input file to the block configuration:
- Click next to the Inputs header in Block properties and choose Input file from the drop-down menu.
- In the Add an input file dialog, enter the alias you want to use for this file - for instance,
working journal. This is not the file name; it's how you reference this file in your configuration. In particular, this alias is used in port names. - Click OK in the dialog.
A new input port
Input files.working journalappears in Inputs. You'll pass the journal file with new parameter values to this port. - Link the
Output fileport of the Text block to theInput files.working journalinput. -
On the
Input files.working journal.Save asport, set a path relative to the project folder where the input file should land:user_files\journal.ajn. You don't need to removejournal.ajnfrom your project template: the block will first copy the template to the run host, then write your input files and folders on top of it.By default, files generated by other blocks are temporary and have random names. You have to set both the path (the
user_files\subfolder) and the filename, or the file will end up at a path likeuser_files\~2fed64ca74acefc3. (1)~as the first character is the temporary file naming convention in pSeven Enterprise.
-
On the
Runport, write the launch command."C:\Programs\ACME\solver.exe" -B -F model.apj -R user_files\journal.ajnSince the remote working folder contains the full project and is the current working directory when the solver runs, you can use exactly the same command as for a normal launch.
-
To save the solver results to your workflow run directory:
- set the
Results.Maskinput port to*.csv - on the
Results.Store toport, select where to save the files
If your solver produces result files with several different extensions - for example,
.csvand.dat- open the Edit value dialog on theResults.Maskport and switch the type at the top left to List of masks. Add as many masks to the list as you need. - set the
-
To send solver results to another block:
- Add a result folder: click in the Inputs pane,
choose Result folder, enter its alias:
designs. - Set the
Result folders.designs.Take frominput port to.(a dot). This tells the block to collect results from the remote working folder root - that is, from the working project folder. - Set
Result folders.designs.Maskto*.csvto collect only CSV files. - Link the
Result folders.designsoutput port to the block that post-processes the results.
If you want to also save a copy of this output folder in workflow results, set the save location on the
Result folders.designsinput port. Choose a location inside the workflow run directory - the block cannot write any files outside it.Allowed save locations for output files
Blocks cannot write files outside the current workflow run directory. It is recommended that you keep the default file location in the file dialog ("Block working directory") and only change the path. Another allowed location is "Workflow or run" with a relative path - with such settings, the block will save the file to the run directory root.
- Add a result folder: click in the Inputs pane,
choose Result folder, enter its alias:
Verify paths before the first real run
To check that paths in file and folder settings are correct,
you can replace your actual Run command with echo and ${...} aliases.
echo %cd% - "${Remote working folder}" - "${working journal}"
The block resolves all ${...} aliases to absolute paths on the run host,
which are determined by your settings for
Remote working folder.Path, Remote working folder.Create subfolder, and file locations.
The workflow run log will show the actual paths the block resolved.
%cd% is a Windows system variable that contains the current working directory path.
Note that %cd% and ${Remote working folder} resolve to the same path.
When the block runs, it creates a temporary remote working folder on the run host, copies all contents of your project template there, and launches your software with that folder as the working project. Once the software exits, the block collects result files, copies them to the workflow run directory, and outputs to ports - according to your settings.
This is a basic example; for full details about software launch on the run host and related settings, see How it runs.
Running scripts¶
If you have a script (.bat file) you normally use to launch your software,
you can run this script in the Program block with minor modifications.
- Select a Program block in your workflow to view its settings in the Block properties pane. Program blocks are entirely configured in this pane; opening the block just displays its configuration overview.
- At the top of the Block properties pane, under "Run on:", select the run host.
- Add input files and folders, result files to the block configuration.
Set their aliases in the add dialogs - for example,
settings file,project,journal. -
In your script, replace file paths with
${...}aliases.@echo off "C:\Programs\ACME\preprocessor.exe" -prepare "${settings file}" "C:\Programs\ACME\solver.exe" -B -F "${project}\model.apj" -R "${journal}" -
Open the Edit value dialog on the
Runport and switch the type at the top left to Script. Paste your script there.
When the block runs, it creates a temporary remote working folder
on the run host and copies all input files there.
Then it resolves all ${...} aliases in the script, writes it to a temporary file,
and passes that file to the system interpreter.
The remote working folder becomes the current working directory for the script.
Once the script exits, the block collects result files and copies them to the
current workflow run directory, then outputs their storage paths to ports.
This is a basic example; for full details about program launch on the run host and related settings, see How it runs.
How it runs¶
The sections above provide basic examples, assuming that most settings - in particular, logging and error handling - are left at their defaults. In most cases, your tasks will require certain adjustments to that basic configuration, depending on the features of the software you're integrating, the desired file layout, workflow behavior, and so on.
Knowing how the block launches programs on the run host helps you adjust the block for your specific scenario.
During a workflow run, pSeven Enterprise sends the block to the run host you've selected and starts it there. Here's the breakdown of what happens next.
-
The block creates a remote working folder on the run host. This is either a temporary folder or the folder specified in
Remote working folder.Path, with an optional subfolder.-
If
Remote working folder.Create subfolderis enabled, the block creates a unique subfolder inside the remote working folder for each run. The resulting path is:{Remote working folder.Path or temporary folder}\{random subfolder if Remote working folder.Create subfolder is True}\This ensures that parallel runs of the same block - for example, runs inside a loop or in batch mode - do not interfere with each other's files.
-
You can use
echo %cd%orecho ${Remote working folder}as theRuncommand to check the resulting working folder path on the run host.
-
-
The block copies all contents of the folder specified by
Remote working folder.Prototypeto the run host, placing them at the remote working folder root. -
The block copies the input files and folders to the remote working folder.
- Locations are determined by your settings on the
Input files.{file}.Save to,Input files.{file}.Save as,Input folders.{folder}.Save to,Input folders.{folder}.Save asports. If a file or folder location is not specified, it lands at the remote working folder root by default. - Input files overwrite existing files copied with the remote working folder prototype, if they have the same names and paths.
- Input folders are merged with the prototype folders, if they land at the same path.
The path to a file or folder is generally:
{Remote working folder}\{"Save to" setting}\{"Save as" setting or original filename} - Locations are determined by your settings on the
-
The block resolves
${...}aliases in theRuncommand.- File and folder aliases are replaced with absolute paths to their copies on the run host (inside the remote working folder).
- Substitution and environment variable aliases resolve to their port values.
-
The block sets environment variables if you've added them to the block configuration.
The variables are set for your program or script only - so the environment settings are temporary. The block never changes variables in the system environment.
-
The block sets the remote working folder as the current working directory and executes your
Runcommand or script there. -
While the command runs, its console output is captured by the block and shown in the Run log pane.
See Logging for other logging features available in this block.
-
Once the command exits, the block checks its exit code and collects the configured result files and folders.
- If the command exits successfully, the block looks for result files
at the locations resolved by the corresponding
${file}aliases or determined by your file location settings (Result files.{file}.Take from,Result folders.{folder}.Take from). - If a required result file is not found at its expected location, the block treats this as a command error.
- If the command exits successfully, the block looks for result files
at the locations resolved by the corresponding
-
The block copies the collected result files and folders from the run host to the current workflow run directory.
- These copies are temporary by default. They are stored in the run directory only while other blocks use them during the workflow run.
- The storage paths of the copied files are sent to the corresponding output ports.
- If you configure a save path for the result, the file is also saved there as part of the workflow run results.
-
If the command has completed successfully and all required result files have been found, the block outputs the corresponding result ports and signals completion through the
@gooutput port.The block also outputs the program's exit code through the
Exit codeoutput port. -
If the program exits with an error code (not in
Success codes), or a required result file is not found at its expected location, or an error message was detected in logs, the block stops with an error by default and doesn't output anything.You can set up error handling to change this behavior.
-
After the command has finished and the block has collected its results, the remote working folder is cleaned up according to your
Remote working folder.Cleanupsetting.By default, the cleanup removes all copies of input and result files on the run host.
If you need to inspect files on the run host for troubleshooting, switch
Remote working folder.Cleanupto "Disabled".
Input files¶
When the Program block runs, it creates copies of all input files on its run host before the program launch. By default, every such copy lands directly in the remote working folder (at its root) under the same name as the original file. If a file with that name already exists in the remote working folder, there are two cases:
- The existing file comes from the remote working folder prototype. The input file overwrites it; this behavior is intended to support running engineering software.
- The existing file is another input file. The block stops with an error: input files cannot overwrite each other - they can only overwrite the prototype's files.
If your program accepts file paths as command line arguments,
add ${...} aliases to the command on the Run port.
The block replaces the aliases with absolute paths to working copies of input files on the run host.
thetool -i "${input file}" -o "${output file}"
If your program needs files at fixed locations - with specific filenames or in certain subfolders in its working directory - configure where each file should land using these input ports:
Input files.{file}.Save to- path to the subfolder where the file should be placed, relative to the working folder or project folder. The file keeps its original name, unless you also setInput files.{file}.Save as.Input files.{file}.Save as- the name under which the file is saved.
As a shortcut, you can also set both the path and the filename
on the Input files.{file}.Save as port (subfolder\path\filename.ext),
and leave Input files.{file}.Save to unset.
For files received from other blocks, the name setting (Input files.{file}.Save as) is often required.
Such files have random names by default; see the examples below for details.
Place an input file from storage in a required subfolder
Assume a program reads its input from INPUTS\input.dat in the folder where it runs,
with no command line option to specify the path.
- Upload
input.datto the workflow folder or another place in your storage. - Add an input file in block settings. Give it an alias -
datfile, for example. - On the
Input files.datfileport, select the file from your storage. - Set the
Input files.datfile.Save toport toINPUTS.
Before running the program, the block will place the file
at INPUTS\input.dat inside the program's working folder.
You don't need to specify Input files.datfile.Save as,
unless you want to rename the file in the working folder.
For example, you might store it as input_template.dat
but set Input files.datfile.Save as to INPUTS\input.dat,
so the file ends up at INPUTS\input.dat as expected by the program.
Alternatively, you can set INPUTS on Input files.datfile.Save to
and input.dat on Input files.datfile.Save as,
if you need these settings as separate ports.
Place an input file from port in a required subfolder
Assume there's a CSV input file generated by another block,
which you need to place at model_files\user\designs.csv inside the working project.
- Add an input file in block settings. Give it an alias -
design file, for example. - Link the other block's output to the
Input files.design fileinput. - Set the
Input files.design file.Save asport tomodel_files\user\designs.csv.
By default, files generated by other blocks are temporary and have random names.
You have to set both the path and the filename,
or the file will end up at a path like model_files\user\~2fed64ca74acefc3. (1)
~as the first character is the temporary file naming convention in pSeven Enterprise.
Alternatively, you can set model_files\user on Input files.design file.Save to
and designs.csv on Input files.design file.Save as,
if you need these settings as separate ports.
Result files¶
After your program runs, the block collects result files from the remote working folder
and copies them to the workflow run directory (in your storage), where other blocks can get them.
Storage paths of these copies are sent to the block's output ports.
Copies in the storage are temporary by default: they are deleted automatically,
except the files you choose to retain by setting their storage location
on the Result files.{file alias} input port.
To find a program result file, the block requires you either
to include the file's ${...} alias in your commands or
to set the Result files.{file alias}.Take from input port.
- If you use the
${...}alias, the block assigns the file a location automatically: it generates a path, which you have to pass to the program as a command line argument. - If your program doesn't accept paths as command line arguments
and writes output files at fixed locations,
set their paths on the
Result files.{file alias}.Take frominput ports. These paths are relative to the remote working folder. After your program finishes, the block looks for result files at these paths. - You can use both: if
Result files.{file alias}.Take fromis set, the${...}alias of that file resolves to an absolute path determined by the port setting. - If you use neither, the block stops with an error before running your program.
If, after the program exits, any output file isn't found at its expected path,
the block treats this as a program error, which it handles according to your
Command error port setting.
To save an output file, set its save location on the Result files.{file alias} input port.
It can be:
- a storage path relative to the block working directory in the current run directory (select "Block working directory" in the file dialog), or
- a path relative to the root of the current run directory (select "Workflow or run" in the file dialog).
Note that the block cannot write output files outside the current run directory. That is, writing to the workflow folder and other folders is prohibited for all blocks.
Result files.{file alias} output ports send file paths regardless of the save location setting.
For files with the Result files.{file alias} input unset,
the output paths point to temporary file copies in the current workflow run directory.
Those copies have random names without extension by default, like ~2fed64ca74acefc3.
If you want to send a file to another block,
which requires certain extensions for input files,
there are two options:
- Set a save location for the file on its
Result files.{file alias}input port. Use any name and the required extension. - If you want the file to be temporary,
set the filename on
Result files.{file alias}to~.{extension}- for instance,~.prt. With this setting, the block will output a temporary file with a random name and your extension, like~2fed64ca74acefc3.prt.
~ as the first character is the temporary file naming convention in pSeven Enterprise.
If there's a filename that starts with ~ in your settings,
the block will generate a random name for that file.
Input and output folders¶
Folders are generally set up the same way as files.
- Input folders are copied to the remote working folder before running the program.
- By default, an input folder lands at the remote working folder root under its original name.
Input folders.{folder alias}.Save toandInput folders.{folder alias}.Save assettings control folder placement the same way as for input files.- If a folder with the same name already exists on the run host, and that folder is part of the remote working folder prototype, then the input folder merges with the existing one, and files from the input folder overwrite existing ones.
- If such a folder exists but it is another input folder (not part of the prototype), it causes an error: input folders cannot merge with each other - they can only merge with the prototype's folders.
- Result folders are collected from the run host after the program finishes.
- To make the block find and collect result folders,
you have to include their
${...}aliases in your command or script or set their paths on theResult folders.{folder alias}.Take fromports.
Folders support an additional file copy mask setting:
Input folders.{folder alias}.Mask- if set, only the files that match this mask are actually copied to the remote working folder.Result folders.{folder alias}.Mask- if set, only the files that match this mask are included when the block saves the result folder or sends it to an output port.
Example masks
*.dat- all files with the.datextension in the folder root; doesn't match files in subfolders**\*.dat- same, but also matches.datfiles in all subfoldersresult-??- folders namedresult-01,result-02, and so onresult-??.*- files with any extension namedresult-01,result-02, and so on
For simple masks such as *.dat, enter them in the port value field in Block properties.
For more complex masks - for example, if you need two or more kinds of files with different extensions -
open the Edit value dialog on the mask port and switch the type at the top left to List of masks.
Add as many masks as you need; the block will include any file that matches any mask from the list.
Use masks to avoid copying large files
Engineering project folders often contain files that don't need to travel to the run host: cached geometry, binary results from previous runs, mesh databases. Adding an input folder mask limits what the block copies, which can save noticeable time, especially if the Program block runs in a workflow loop.
Program options as ports¶
Options are additional command line arguments that change program settings.
For example, many engineering solvers support an option that sets the number
of solver threads - usually -n {number of threads}.
The command line might include many options:
thetool.exe -n 4 -a -R -i "D:\Work\Project X\input.dat"
You can expose program options as ports by adding substitutions in block settings.
- Click in Inputs, select Substitution, enter its alias - for example,
N threads. - The
Substitutions.N threadsport appears. Set its value to4. - Add another substitution, enter its alias:
Options. Set it to-a -R. -
Use the aliases in your command on the
Runport:thetool.exe -n ${N threads} ${Options} -i "${input file}"
The ${N threads} and ${Options} aliases are replaced with port values when the block runs.
You can change program settings by editing port values or sending them from other blocks.
Environment variables¶
Your program might read settings from environment variables -
for example, get the path to its license file from the TT_LICENSE_FILE variable.
You can set or override that variable on the block's run host:
- Click in the Inputs pane, select Environment variable.
- In the Add environment variable dialog,
enter the exact name of the variable:
TT_LICENSE_FILE. - The
Environment variables.TT_LICENSE_FILEport appears. Set its value to the license file path on the run host.
The block sets the TT_LICENSE_FILE variable for the program only.
It doesn't change the system TT_LICENSE_FILE variable, if it is already set on the run host.
The environment variable settings in the block are temporary;
they apply only to the program (commands, script) launched by the block.
You can test environment variables in Windows
Setting environment variables via the block is similar to opening a command prompt, setting variables there, and running your program from it:
- Open a new command prompt window.
- Set the variable you're testing - for instance:
set TT_LICENSE_FILE=C:\Licenses\The Tool v123.lic. This sets it only for the current window. - Run your program in the same window. The program inherits the variable you've set.
You can also set variables inline in the Run command, before the program call:
set TT_LICENSE_FILE=C:\Licenses\The Tool v123.lic && thetool.exe ${options substitution} -i "${input file}"
Or, if the program reads settings, input and output paths from environment variables:
set TT_OPTIONS=${options substitution} && set TT_INPUT=${input file} && thetool.exe
Logging¶
By default, the block captures all messages output by your program - the stdout and stderr streams of your command or script - and relays all captured messages to the workflow run log. You can view it in the Run log pane on a workflow run tab.
To suppress program logs in the workflow run log,
set the Logging.Show command log input port to No.
With this setting, the block only logs its own errors and warnings -
for instance, if it can't find a program output file you've specified.
To save the full log to your run results, set these input ports:
Logging.Log file: save location. Default:command.login the block working directory in the current run.Logging.Save log file: when to save the full log. By default, the block saves it only if your program (command, script) exits with an error.
If your program writes logs to a file rather than the standard output,
set Logging.Command log file to the location of that file.
Use a file name, path relative to the remote working folder,
or an absolute path on the run host.
While your program runs, the block reads that file
and adds its contents to the run log and to the full log file.
Solver that writes log to a file
Some engineering solvers write all messages to a .log file in the project folder.
If you run such a solver without the Logging.Command log file setting,
its messages won't appear in the run log,
and Logging.Fail pattern won't work, since the block has nothing to monitor.
Set Logging.Command log file to the log file name or path relative to the project folder -
for example, solve.log or logs/main.log.
The block will read that file continuously while running
and relay new messages from the file to the run log and to the full log file.
Handling program errors¶
If an error occurs in your program or script, the block stops with an error by default and doesn't send anything to its output ports. It also doesn't store any result files to the workflow run directory but will save the full log file according to your logging settings.
To detect errors, the block uses the exit code of your program or script. If the program doesn't set a specific exit code on error, you can set up the block to detect errors in logs.
If you switch the Command error input port to "Best effort",
the block suppresses command and program errors:
it finishes normally and sends outputs for troubleshooting.
- The exit code is output to the
Exit codeport. - If you've set up saving a full log, the log file is saved and output to the
Log fileport. - Result file and folder ports output the program results, if those files and folders exist on the run host. If they don't, the ports output Path values pointing to their expected locations in the workflow run directory.
This behavior enables designing workflows that are robust to errors in integrated programs or scripts.
- If downstream blocks that receive files from Program
can handle missing input files,
simply select "Best effort" on the
Command errorport and link file outputs directly to those blocks. - Otherwise, use a Condition block to check the exit code sent by Program (the
Exit codeport). Set up links between Condition and downstream blocks so they get the input files only if the exit code is 0. If you've set a custom list of success codes on theSuccess codesinput, set up Condition to check that the exit code is in that list.
Program errors and block or system errors are different
The Command error setting affects block behavior
only in cases when errors occur in the program - for example:
- the program or script exit code is not in the list of success codes (the
Success codesport) - the program has timed out
- an error message is detected in the program logs
- the program didn't write its expected outputs - the result files you've set up in the block
The block can detect and handle such errors because it controls the program launch and can monitor the program's processes, its outputs, exit codes, and so on.
The block cannot handle system errors - for example, if the host computer
runs out of memory, Windows stops the block process, or you stop the workflow run.
Also it does not handle errors caused by misconfiguration - for example,
if you set the same name for two input files (same Input files.{file 1 or 2}.Save as setting),
or attempt overwriting a subfolder from the remote working folder prototype
with an input file (files can't overwrite folders, folders can't overwrite files).
In such cases, the Command error setting doesn't affect the outcome,
which is usually a block error that stops the workflow run.
Using exit codes¶
To detect program errors, the block uses the program's exit code.
It is an integer value that every program sends to the operating system
when it finishes, errors, crashes or otherwise terminates its process.
In Windows, this is also known as error level
or the built-in ERRORLEVEL variable in batch scripts.
If the Program block stops a workflow run due to an error in the program,
usually there is a line in the run log that shows the exit code.
Commonly encountered error codes are:
- 1 - general error
- 2 - user error: wrong option, incorrect syntax
- 127 - system command not found (in Linux)
- 9009 - system command not found (in Windows)
Certain exit codes are set by the block
Exit codes 100 and 124 are special. They are set by the block, replacing the program's exit code.
- 100 - You've set up error detection in logs,
and the block has detected an error message but didn't stop the program immediately.
This can occur only if you've also set
Command errorto "Best effort"; see Detecting errors in logs for details. - 124 - You've set a time limit, and the program timed out so the block interrupted it.
Programs can define their own exit codes. The general convention is that the only success code is 0, and errors are indicated by codes 1 or greater. However this convention is not enforced by the OS, so certain programs ignore it - for example:
- Some programs always exit with the code 0, so their errors are not detectable by the exit code. In this case, if the program prints error messages to its log, you can detect errors in logs.
- Some exit with a non-zero code when they finish with a warning while producing results normally.
If this is your case, add such codes to the list on the
Success codesinput port.
To find the codes your program uses, check its documentation and command line help.
If the codes are not documented, test running the program from the command line
with wrong options, invalid or missing inputs and so on.
After each program launch, type echo %ERRORLEVEL% - it outputs the exit code of the preceding command.
Checking program exit codes in Windows
rem Normal launch assuming the input file exists and is valid, the project folder is writable and so on.
rem Exit code should be 0.
thetool -i "D:\Work\input.dat" -o "D:\Work\result.dat"
echo Exit code: %ERRORLEVEL%
rem A typo in a system command (`dir /o`).
rem Exit code should be 9009 because "&&" stops execution if there's an error in the preceding command.
die /o && thetool.exe
echo Exit code: %ERRORLEVEL%
rem Invalid option -BAD.
rem Exit code should be 1 or greater, commonly 2.
thetool -BAD -i "D:\Work\input.dat" -o "D:\Work\result.dat"
echo Exit code: %ERRORLEVEL%
If the program returns non-zero codes on success,
or you want to ignore certain errors,
add those codes to the list on the Success codes input port.
Programs that use non-zero codes for warnings
Some programs use exit codes to communicate more than success or failure. For example, a mesh generator might return:
- 0 - clean run
- 4 - completed with mesh quality warnings (result is usable)
- 8 - completed with errors (result may be unusable)
If code 4 is acceptable in your workflow, add it to Success codes, making it (0, 4).
Don't remove 0, or the block will treat clean runs as errors.
Detecting errors in logs¶
Engineering tools often return exit code 0 (success) even on failure - for example, when a convergence criterion isn't met, a license error occurs, or a mesh quality check fails. In such cases, the exit code gives no information, but you can still detect program errors by monitoring its logs.
On the Logging.Fail pattern input port,
set one or more strings that only appear in your program's error output.
- Run the program normally with a known-bad input, which makes the run fail.
- Search the program's output or log file for a consistent error indicator.
For example, error messages might start with
Error:or contain details such asConvergence not achievedorLicense checkout failed. -
Copy the identifying part of the message to the
Logging.Fail patterninput port.- If you need to detect many different messages, open the Edit value dialog
for the
Logging.Fail patternport and switch the type at the top left to List[String]. Add as many message strings as you need.
- If you need to detect many different messages, open the Edit value dialog
for the
While the block runs, it monitors the program's standard output
and the log file - if you've set Logging.Command log file.
If any message there contains any of the strings you've added on Logging.Fail pattern,
the block treats this as a program error:
- With
Command errorset to "Block error" (default), the block stops immediately. -
With
Command errorset to "Best effort", the block continues and doesn't interrupt the program if it still runs.Exit code 100 is a special code set by the block, which you can use to reliably identify the cases when program errors are only detectable in logs.
Once the program finishes, the block checks its exit code:
- If the program has set an exit code that is not in
Success codes, the block outputs it to theExit codeport. - If the program exit code is a success one (0 or other from
Success codes) in spite of errors in the log, the block sends 100 to theExit codeport.
- If the program has set an exit code that is not in
Regular expressions as error patterns
If you're familiar with regular expressions, you can also use them to detect errors.
In the Edit value dialog for Logging.Fail pattern,
switch the type to RegEx or List[RegEx], and input your expressions.
Setting a run time limit¶
On certain errors, a program might stop responding but not exit -
causing the block to wait indefinitely.
To prevent this, set a run time limit with the Timeout input port.
When this limit is reached, the block interrupts the program, sets exit code to 124,
and handles the error according to your Command error setting.
Accepted formats:
1d 2h 34m 56s- days, hours, minutes, seconds. Any combination works:1d 12h,5h,30m, and so on. Spaces are optional.27:34:56- hours:minutes:seconds. Hours can exceed 24.95696- seconds.