Click here to Skip to main content
Email Password   helpLost your password?

Script.NET

S_.gif

New version of Script.NET was released. (13 June 2008)

It is now based on Irony Compiler Toolkit and has new run-time infrastructure.

Please use following link to download it: Download Latest Version.


scripttest.gif

Script .NET is a simple scripting engine which can be embedded into .NET framework applications to perform custom functionality in run-time. It works like VBA in Microsoft Office Applications. The difference is that Script .NET may use custom object model, different for each application. Script .NET is written in C#.

The key principles of Script .NET are:

The idea of Script .NET was born 17 September 2007. Then:

In current version I am using C# Compiler Tools from http://cis.paisley.ac.uk/crow-ci0/ to produce Lexical analyzer and language parser.

Getting Started

All you need to start working with Script .NET is to add reference to ScriptDotNet.dll,

Example (in C# code):

using ScriptDotNet;
Script s = Script.Compile(
"MessageBox.Show('Hello .NET! This is Script .NET');");
s.AddType("MessageBox", typeof(MessageBox));
s.Execute();

Types

For the sake of simplicity there are only four commonly known build-in types:

Type Name .NET Analogue Initializer
double double x = 1.23;
long long x = 3;
string string s='Hello World!'
bool bool b = true
array object[] A = [1, 1+2, 'Hello', s]

There is also implicit type object which is .NET object. All other types are derived from it. Script .NET supports type importing. Which means you can add any .NET Framework type to the Script .NET programs and work with it.

Note: If you haven’t added your time Script.NET run-time will search it in libraries loaded into current application domain. If the type was found then it will be cached for further use in Script Context.

Constant's declaration

Boolean = True | False
Object = null
String constants must be in '' brackets, example: s='Hello';

Variables

All variables in Script .NET are global and non-typed. They are stored in the Script Context. Script Context is a special structure which is used by Script Engine to store run-time information and interact with .NET.

However, function body creates local Contexts and store declared variables there. Functions have access to global variables.

Examples of variables:
X, x1, name_of_var.
Variables may be used in expressions, statements. The type information is computed in run-time.

Arrays

The build-in arrays has a .NET type object[] and can store any values. The element of array may be accessed in a usual way: Array[index].

Expressions

There is usual syntax of expressions, like:

X = (y+4)*2;
Y = a[5] + 8;
Z = Math.Sqrt(256);
P = new System.Drawing.Point(3,4);
'this is string' is string

Expressions have following operators:

+, -, *, / ,%, ! , | , & , != , > , < , is

There is also special operator new for creating instances of imported types.

Statements

A program in Script .NET is a sequence of statements. There are three usual statements: sequencing (;), loop, and branching.

If ... Then ... Else ...

if (Expression) statement else Statement

Example:

if (x>0) y = y + 1 ; else y = y – 1;
if (x>0) message = 'X is positive';

For ...

for (Expression1;Expression2;Expression3) Statement

Example:

sum=0;
for(i=0; i<10; i++) sum = sum + a[i];

Foreach ... in ...

foreach (Identifier in Expression) Statement

The result of Expression calculation must implement IEnumerable. Expression evaluates only once, before loop starts.



Example:

arr=[1,2,3,4,5]; sum = 0;
foreach(i in arr ) sum = sum + i;

While ...

while (Expression) Statement


Example:
while (i>0) i = i-1;

Switch

switch (expr){
case expr1: statement
...
default: statement
}

Example:
switch (i){
case 1: MessageBox.Show('Hello!');
case 2: MessageBox.Show('?');
default: MessageBox.Show('No way');
}

Break, Continue

Has usual meaning, may be used only inside the loop

Return

Used only inside function call

Functions

function (id1, id2, ... , idn) {
Statement }

The function is creates local context during execution.

Example:
function fac(n){
if (n==1) return 1;
else return n*fac(n-1);
}
MessageBox.Show(fac(5).ToString());

//pointer to a function
Func_pointer = fac;
Func_pointer(4); //Call function using pointer

Reserved functions

event – assign event to windows forms control
eval – evaluates value of an expression
clear – clears all variables in context

Script Context

Script Context is an object stores run-time information: variables and import types. Using Script Context you can add .NET objects to use in the script.

There are a number of functions:

Using .NET objects from Script.NET

  
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ScriptDotNet;

namespace Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {

             Script s = Script.Compile(@"form.Text = 'Hello World'; 
               MessageBox.Show('Hi'); 
               b = new Button()  ");

            s.AddObject("form", this);
            s.AddType("Button", typeof(Button));
            s.AddType("MessageBox", typeof(MessageBox));
            s.AddBuildInObject(typeof(Math));

            s.Execute();            
        }
    }
}
   

Script.NET in .NET Applications

All you need to start working with Script .NET is to add reference to ScriptDotNet.dll,

 
using ScriptDotNet;
...
Script s = Script.Compile(
                 "MessageBox.Show('Hello .NET! This is Script .NET');");
s.AddType("MessageBox", typeof(MessageBox));
s.Execute();            
 
 

Script Test

Script Test is the application for testing Script.NET programs. You can use it to execute any scripting program and to observe results in Script Context.

scripttest.gif

Mutantic Framework

Mutantic Framework introduces a special kind of "meta" objects for working with objects of any type.

Definition: Mutant is a special object which could have all properties (fields, methods, etc), and may be converted to any type (or assigned to object of any type). The semantics of such conversion (or assignment) is pragmatically conditional, i.e. depends on user needs.

Example. Creation and Usage of MObject:

// Create Data Mutant Object
a = [ Text -> 'Hello from Mutant' ];
// Set Additional Fields
a.Top = 0;
a.Left = 0;
// Set corresponding fields of Windows Form object
// (Mutantic Assignment)
form := a;

Meta Programming

Script .NET has a special quotation operator: <[ program ]> which returns AST of a given program. The AST of the current program may be accessed with prog object.

Here is an example: Modification of current script

//Create an AST for MessageBox.Show('Hello'); program
ast = <[ MessageBox.Show('Hello'); ]>;
//Add this AST at the and of the current program
prog.AppendAst(ast);
MessageBox.Show(prog.Code());

The <[ ... ]> operator and prog object allows Script.NET to generate new scripts or modify existing script at the run-time.

Alternative Solutions:

External Links

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
QuestionIronyScriptDotNet
TheChindu
2:16 28 Apr '09  
Great code. Great article. why don't you update it to match IronyScriptDotNet
AnswerRe: IronyScriptDotNet
Extrim
5:48 29 Apr '09  
Thanks and I am continuosly working to improve it. That is why I don't have time to update the article. But you are right I should update it and I'll definitely do that.
GeneralI was looking for some thing like this
TheChindu
0:11 28 Apr '09  
i was looking for some thing like ms script control for .net that would be easy to use and would allow extension using .net objects. Script# saves the day.Got my 5.
GeneralIssues with Math.Abs
frozenpondlife
4:07 11 Feb '09  
Piter,

I have just tried using a simple script that works on one PC on another PC, with different results.

This is the script:

for (i = 0.0; i < 5; i += 0.5)
{
WriteText("Abs(" + i + ") = " + Abs(i) + "CRLF");
}


It is meant to calculate the absolute of i. WriteText() outputs the text on screen and the "CRLF" adds "\r\n".

This is the correct output on the first PC (It doesn't do anything to the values, as all i's are positive):

Abs(0) = 0
Abs(0.5) = 0.5
Abs(1) = 1
Abs(1.5) = 1.5
Abs(2) = 2
Abs(2.5) = 2.5
Abs(3) = 3
Abs(3.5) = 3.5
Abs(4) = 4
Abs(4.5) = 4.5

Here's the output of the second PC, using the same three lines of code:

Abs(0.5) = 0
Abs(1) = 1
Abs(1.5) = 2
Abs(2) = 2
Abs(2.5) = 2
Abs(3) = 3
Abs(3.5) = 4
Abs(4) = 4
Abs(4.5) = 4

This is obviously wrong.

The only thing I can think of is a difference in the .NET versions on the two computers. The PC where it works has .NET 1.1 and .NET 2.0. The PC where it doesn't work has .NET 1.1, .NET 2.0, .NET 3.0 and .NET 3.5 installed.

Any idea what could cause this?

Thanks in advance.

Christian
GeneralRe: Issues with Math.Abs
frozenpondlife
4:54 11 Feb '09  
Please don't be confused by the "'s in the code. They are replaced by ' in a preprocessor.

Christian
GeneralRe: Issues with Math.Abs
frozenpondlife
5:08 11 Feb '09  
I have now removed .NET 3.0 and .NET 3.5 from the second PC. Still no improvement.
GeneralRe: Issues with Math.Abs
Extrim
7:45 11 Feb '09  
I will investigate your problem and will come back as soon as possible
GeneralRe: Issues with Math.Abs
frozenpondlife
8:52 11 Feb '09  
Piter,

thanks. I have tried a few others, like Math.Ceiling() and Math.Cos() and they work as expected.

Christian
GeneralRe: Issues with Math.Abs
Extrim
22:31 12 Feb '09  
Hello,

Please check the issue on the up-coming release. If it will be still reproducible give me a note on piter.protsyk@gmail.com

http://www.protsyk.com/scriptdotnet/versions/130208/

Regards,
Petro
GeneralRe: Issues with Math.Abs
frozenpondlife
6:26 14 Feb '09  
Petro,

thanks for your answer. I will try it over the next few days.

Christian
GeneralRe: Issues with Math.Abs
frozenpondlife
5:52 23 Feb '09  
Petro,

With the new version I am getting a few errors:

 
using ScriptNET;
using ScriptNET.Runtime;

.
.
.

Script s = null;

s = Script.Compile(script);

s.AddBuildInObject(typeof(Math)); // to use maths library

s.AddObject("report", report); // for report generation

s.AddType("DateTimePicker", typeof(DateTimePickerUI));


Note: I have added 'IronyScriptDotNet.dll' as a reference.

All three cause a 'ScriptNET.Script' does not contain a definition for ... error.

Any idea why this could be?

Thanks

Christian
GeneralRe: Issues with Math.Abs
Extrim
21:14 23 Feb '09  
Hello Christian

It seems that you might use an older version of Script.NET.
Please download the latest by the following link:
http://www.protsyk.com/scriptdotnet/versions/latest/IronyScriptDotNet.zip

Then change a definition:

using ScriptNET;
using ScriptNET.Runtime;
.
.
.
//This should be executed once per application, before executing any script
RuntimeHost.Initialize();
RuntimeHost.AddType("DateTimePicker", typeof(DateTimePickerUI));

Script s = null;
s = Script.Compile(script);

//s.AddBuildInObject(typeof(Math));
// please see using statement

s.Context.SetItem("report", report); // for report generation

Regards,
Petro
GeneralRe: Issues with Math.Abs
frozenpondlife
2:20 1 Mar '09  
Hi Petro,

unfortunately, this still doesn't work.

The version at this address doesn't contain a definition for 'SetItem' (see s.Context.SetItem("report", report); // for report generation).

The help file doesn't mention using ScriptNET.Runtime;.

Is it possible that this version is not the latest version?

Thanks for your help.

Christian
GeneralRe: Issues with Math.Abs
Extrim
3:02 5 Mar '09  
Hello Christian,

The help file is not synchronized with the latest code. Sorry for that, the code evolving much more faster than documentation.

Please consider examples that comes together with a script.net solution and take a look at unittests. Unittest should show expected behavior of scripting engine.

Regards,
Petro
GeneralSimplifying use for person writing the script / security
frozenpondlife
5:31 19 Mar '08  
Hi Extrim,

just started playing with this and it looks great, because of its simplicity.

Here's my question: In your example

Script s = Script.Compile(@"form.Text = 'Hello World';
MessageBox.Show('Hi');
b = new Button() "
);

s.AddObject("form", this);
s.AddType("Button", typeof(Button));
s.AddType("MessageBox", typeof(MessageBox));
s.AddBuildInObject(typeof(Math));

s.Execute();


the person writing the script will have to type in "form.Text = ..." to change the content of "Text". Is it possible to have them just type "Text = ..." to access form.Text? Hope this makes sense.

There is another aspect: The way the example is written, the person writing the script can access all public variables in "form". This might not be desired and could cause serious problems. Is there a way to limit what the user can access?

Thanks for your answer.
AnswerRe: Simplifying use for person writing the script / security
Extrim
6:13 19 Mar '08  
Hello!

Thank you for your questions. You have rised good points.

Unfortunatelly, now it is not possible to use just object's properties, like "Text = ...".
The only thing you could do is AddBuildInObject which will be acessible for reading.
In this example you could write:
"Pow(2,3)" which will be refered to "Math.Pow(2,3)".

There are also no possibility to limit the users accessability.

However, I will keep your requests in mind. I am planning to release new version of Script.NET engine soon. Hopefully, I will try to implement most of the requests.

Best wishes,
Piter (Extrim)
GeneralRe: Simplifying use for person writing the script / security
frozenpondlife
8:24 1 May '08  
Piter,

I would still recommend using it, simply because it is so easy to use.

One question: Is it possible to interrupt a running script from within the C# program?

Thanks

Christian
GeneralI've been playing with this all day...
martin_hughes
12:09 14 Mar '08  
...and it's simply brilliant! Easy to use, easy to deploy and it has opened my eyes to the possibility of delivering scriptable applications to my clients.

Well done, and keep up the good work!
GeneralGreat Idea
merlin981
4:56 8 Feb '08  
Thank you for sharing this. Regardless of whether this can be done with other tools, the point is that this shows how we can make our own script manager. 5 from me



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Rhabot - World of Warcraft Bot

Atlantis WoW - Free Private World of Warcraft Server

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Generalyet another bicycle
George_Saveliev
10:14 14 Jan '08  
but got my five Smile
GeneralCAUTION!
sam.hill
7:34 14 Jan '08  
The "online test" site attempts to run scripts from a site ominously named "spylog.ru".
May be innocuous, but who knows?
GeneralRe: CAUTION!
Extrim
9:15 14 Jan '08  
"spylog.ru" script is simply a counter at the bottom of the page.
GeneralPerfect tool for reports and such.
Gevorg
5:05 14 Jan '08  
I have been waiting for something like this for 3 years already.
For my desktop application i used to have vbscript files that generate HTML as reports and then they i would open up an IE to show report to user.

And usually there might be tight integration with passing objects and such between application and report. So this solution is perfect for .NET applications.

It allows me to distribute/modify reports on a fly.

My site - Body Jewelry
Not my site - Piercing info

GeneralRe: Perfect tool for reports and such.
Extrim
5:30 14 Jan '08  
Thank you!
GeneralRe: Perfect tool for reports and such.
Z.J.Liu
4:20 17 Dec '08  
strong agree with this. if you truly want to find something to use in your application, you will find it's difficult to get a proper one. some years before I was in a reporting system, I have the same feeling with Jewelry. thanks Extrim for your great job, I will use this next time.

Zhijun Liu


Last Updated 17 Dec 2008 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010