CS Script Runtime Environment (script reflection) - oleg-shilo/cs-script.net-framework GitHub Wiki
Objective
The script engine is a small runtime environment and as such it has some characteristics, which may be accessed/analysed 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 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 Web server 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. You can read in details about all aspects of the CS-Script Runtime here and this article will only describe the most common scenarios.
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 a and potentially multiple scripts can be executed during the session.
Note: CS-Script always injects AssemblyDescriptionAttibute with the path of the script providing the all conditions below are met:
Settins.InjectScriptAssemblyAttribute
is set totrue
. This is the default configuration.- The engine is configured to use the embedded CodeProvider. This is the default configuration.
- If a custom CodeProvider is enabled (
Settings.UseAlternativeCompiler != ""
) and the script syntax is C# (file has '.cs' file extension).
Location of script assembly file
The simplest way of finding the file name of the script being executed is by querying environment variableEntryScriptAssembly
;
string asmFile = Environment.GetEnvironmentVariable("EntryScriptAssembly");
However, similarly to the script name, the most accurate approach is to analyze the that data, which is specific to the assembly being executed. This can also be done via environment variable. The name of the variable is composed from 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
.
More samples on how obtain the script name from the script can be found in the ReflectScript sample (>cs-script<\Samples\ReflectScript.cs).