Skip to content

CS Script Runtime Environment (script reflection)

Oleg Shilo edited this page Jan 3, 2022 · 15 revisions

Objective

The script engine is a small runtime environment and as such, it has some characteristics, which may be accessed/analyzed at runtime from the script code itself (reflection). The most important aspects are the name/location of the script file itself and the compiled script assembly. While it may seem to be a trivial task in some cases, it can be challenging. For example, Assembly.GetExecutingAssembly(). Location will always be null if the script is executed as in-memory assembly (setting in css_config.xml).

The information about the location of the script can be vital for the scenarios that require deterministic knowledge about the location of the modules being executed. For example, a script running web server may need to service static web content located in the same directory where the script is. Thus, the webserver needs to map the physical location to the virtual path.

Another example is a complicated custom assembly probing that needs to be done from script. In such case it's important to know the exact location of the script assembly even if it's not loaded as a memory copy.

CS-Script stores the information about script related locations in environment variables, assembly metadata and global CLR object CSSEnvironment. Over the years of intensive use, it became apparent that the low-dependency approaches (envvars and metadata) are more practical, easier to use and in fact more accurate. Though if you are interested in learning about CSSEnvironment class you can find more details on this legacy documentation page. But this article will only describe the most common scenarios involve the use of environment variables and metadata.

Solution

Location of script file

The simplest way of finding the file name of the script being executed is by querying environment variable EntryScript:

string scriptFile = Environment.GetEnvironmentVariable("EntryScript");

However the most accurate approach is to analyze the script assembly metadata. Specifically AssemblyDescriptionAttribute attribute, which the script engine embeds into every compiled script.

static public string GetScriptName(this Assembly assembly)
{
    return assembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false)
                   .Cast<AssemblyDescriptionAttribute>()
                   .FirstOrDefault()?.Description;
}
...
string scriptFile = Assembly.GetExecutingAssembly().GetScriptName();

The second approach is more accurate as you can use it when you host the script engine in your application and potentially multiple scripts can be executed during the session.

Note: CS-Script always injects AssemblyDescriptionAttibute with the path of the script providing that all conditions below are met:

  1. Settins.InjectScriptAssemblyAttribute is set to true. This is the default configuration.
  2. The engine is configured to use the embedded CodeProvider. This is the default configuration.
  3. If a custom CodeProvider is enabled (Settings.UseAlternativeCompiler != "") and the script syntax is C# (file has '.cs' file extension).

Location of the script assembly file

The simplest way of finding the file name of the script being executed is by querying environment variable EntryScriptAssembly;

string asmFile = Environment.GetEnvironmentVariable("EntryScriptAssembly");

However, similarly to the script name, the most accurate approach is to analyze the data, which is specific to the assembly being executed. This can also be done via the environment variable. The name of the variable is composed of the fixed common prefix and the hash code that identifies the assembly in the current process:

string asmFile = Environment.GetEnvironmentVariable("location:" + Assembly.GetExecutingAssembly().GetHashCode());

Information about script engine

The script engine always set some environment variables at startup:

  • CSScriptRuntime - version of the script engine.
  • CSScriptRuntimeLocation - location of the script engine.
  • css_nuget - location of the NuGet packages scripts can load/reference (applicable only for Windows).
  • cscs_exe_dir - script engine directory.

For the most accurate list of environment variables execute cscs -help.