Executing scripts
Scripts can be executed by opening a script file from the application. This may not be very convenient if the script needs to be run frequently. There are two ways to execute a script from a menu as a command.
Running scripts as a command
The special menu command number 902 indicates that the dat field of the menu item definition record contains a script call.
The dat field contains two strings separated by whitespace:
script_source_file function_call
Here, the script_source_file specifies the path to the source file, and function_call defines the function call, including any arguments.
About automatic build
The system can cache binary scripts and therefore start large scripts much faster.
If the script is started as a menu command or called from another script, and the pathname of the script source file is a relative pathname, the program scans a set of directories to locate the script source file.
If a source file is found, the program checks whether a corresponding up-to-date binary script exists in the binary directory. If no such binary exists, the program compiles the script, stores the binary script in the binary directory, and executes it. Otherwise, the existing binary script is executed.
Important: The automatic build feature does not compare modification dates of script source files included to scripts. In practice, include files rarely change.
Note: If you run a script by selecting it directly from the application menu, or if you reference the source file using an absolute pathname, the program always compiles the script before execution, and the temporary binary file is removed after execution.
How source files are scanned in automatic build
If the source file is specified as macro/<script_src_file>, the following root directories are scanned in this order:
-
%PMS_PROJROOT%/%PMS_PROJNAME%/sde/src/<app>/
-
%PMS_LIBDIR%/src/<app>/
-
%COS Database%/Library
-
%PMS_HOME%/<app>/
Here, <app> stands for the module abbreviation, for example 'pm' for Plant Modeller.
The search order allows customized system scripts to be placed in a project, because the first matching file is used. This means that in version 5 and later it is possible to run scripts from an old sde directory if it exists.
Binary scripts are stored either in %PMS_RUNDIR%/<app>/macro or in the Windows temporary folder if the script is run from COS.
For more information about script execution order, see DM_CALL_SCRIPT, which also includes examples.
Calling scriptlib functions
Note: Scriptlibs are part of the application. Customers should not edit or rebuild scriptlibs, but should use the binary versions delivered with the product.
The special menu command number 1001 indicates that the dat field contains a scriptlib function call.
Scriptlibs are precompiled binary script libraries. In the %PMS_HOME%/dm/macro directory, there is a compile script for the scriptlibs of each module.
It is important to note that, although scriptlibs function like script libraries, the current system does not provide tools for managing them (for example, partial deletion, updates, or additions). The compile scripts work as follows:
-
A module-specific subdirectory is scanned and recursively copied into a file in /tmp.
-
Header files (xxx.h) are collected at the beginning of the file.
-
All non-header script files are appended sequentially.
-
Finally, the combined file is compiled, and the binary is placed in %PMS_RUNDIR%/.<hosttype>/<app>/macro.
Note: Error messages refer to line numbers in the temporary file, not to the original source files. Each application can currently load only one scriptlib file.
The following example demonstrates three ways to run scripts from menus, assuming the application is P&ID.
Menu file:
/* demonstrate three different ways to call scripts from a menu */
nco 1;tit Script demo;;
/* 1) Use Filetool to select the script to be executed */
val 902;str Select and run a macro;icn macros;;
/* 2) Execute a specific script "as a command" */
val 902;str Run a func from a mac file;dat macro/howdy.mac say_howdy("People");icn hello;;
/* 3) Execute a script from the scriptlib */
val 1001;str Call func from the scriptlib;dat sclib_hello();icn sc_hello;;
Corresponding script files:
/* sde/src/pd/macro/howdy.mac */
#include include/dmutil.h
say_howdy(string s)
{
U_MESSAGE("Howdy "+s);
}
/* pms_home/pd/macro/scriptlib/sclibfnc.apd */
sclib_hello()
{
U_MESSAGE("This is a scriptlib function");
}
Scriptlib source files are expected to use the following extensions:
|
P&ID |
.apd |
|
Plant Modeller |
.apm |
|
Piping Isometrics & Spools |
.api |
Displaying compile and load messages
Application defaults can be used to control whether script 'compile' and 'load' messages are displayed. This is done using the SET_INT_DEFAULT(module, name, value) extern function. The relevant modules and names are:
-
ScriptManager/ShowCompiles
-
ScriptManager/ShowLoads
The value can be TRUE or FALSE. The default value for both settings is TRUE.
The following example shows how to disable these messages.
#include "include/dmutil.h"
#define MESSAGES FALSE
main()
{
if(MESSAGES == FALSE)
disable_messages();
else
enable_messages();
return(0);
}
disable_messages()
{
compiles = FALSE;
loads = FALSE;
write_to_appdef(compiles,loads);
}
enable_messages()
{
compiles = TRUE;
loads = TRUE;
write_to_appdef(compiles,loads);
}
write_to_appdef(compiles,loads)
{
st_compiles = SET_INT_DEFAULT("ScriptManager", "ShowCompiles", compiles);
st_loads = SET_INT_DEFAULT("ScriptManager", "ShowLoads", loads);
}
Controlling runtime error message prompting
By default, runtime errors that occur during script execution are displayed in the message pane. These messages can be difficult to notice, especially while a script is still running.
If the environment variable CONFIRM_SCRIPT_RT_ERRORS is set, only the first runtime error in a series requires user confirmation, although all error messages are still shown in the message pane. All users who develop scripts should enable this environment variable. Designers who do not develop scripts typically do not need it. It is recommended to set this variable at the Windows user level so that it applies to all projects for that user.
The confirmation mechanism follows our standard error-confirmation logic: if a runtime error occurs 1,000 times in a loop, pressing OK once (or twice) is sufficient.