CS-Script 3.20.0


Using CS-Script with NAnt


Overview

NAnt is a is a free and open source software tool for automating software build processes.  It uses its own XML based syntax for defining business logic of the build process. The native functionality of NAnt can be extended with custom Tasks implemented as an external .NET assemblies. However in some cases when you do not want to develop a full scale assembly for the task that is frequently changes or not to be reused it might be preferable to specify an assembly in a form of C# script file or even embedded C# code (CDATA). In fact if you can even use other (non-C#) .NET languages if supported.

Thus CS-Script extends NAnt functionality and logically this article should belong to Extending Applications with Scripting chapter but it is represented here as the majority of developers would expect any information about  NAnt to be placed in the Development Tools chapter.

This functionality is similar, in some degree, to the NAnt <script> task. However CS-Script implementation allows unrestricted bi-directional data exchange between NAnt runtime and CS-Script script code and also execution o the standalone C# files which can be developed ans maintained outside of the NAnt environment if required.

CS-Script task can be defined in NAnt script by its name <CSScript />:

<?xml version="1.0"?>
<project name="MyProject" default="build" basedir=".">

    <loadtasks assembly="CSScript.Tasks.dll"/>

    <target name="scriptTest">
        <CSScript file="script.cs" />
    </target>
    
...

CSScript task interface is very simple and supports only a few attributes:
Attribute TypeDescriptionContextRequired
file stringAbsolute or relative path of the script file to execute. 
No embedded C# code (CDATA) specified.false
method boolIndicates if the embedded script code is a method definition only (true) or a full script (false). Embedded C# code (CDATA) specified.false
entryPoint stringDefines static entry point (method name) of the script code.Embedded C# code (CDATA) specified.false
verbose bool Determines whether the task should report detailed build log messages. The default is false.
false

Note: CSScript task interface may very from version to version.

Executing C# script files from NAnt script

You can execute C# file by specifying its path as the file attribute value. The C# script (as any other CS-Script script) needs to have traditional CLR assembly entry point "static Main".

Executing C# script file in isolation

NAnt script:
<?xml version="1.0"?>
<project name="CSScriptTest" default="build" basedir=".">

    <loadtasks assembly="CSScript.Tasks.dll"/>
    
    <target name="ioTest">
        <CSScript file="script.cs" />
    </target
...

C# script (script.cs):
using System;

class Script
{
    static public void Main(string[] args)
    {
        Console.WriteLine("Hi there");
    }
}


Reading and writing project properties from the script
In the following code sample demonstrates how NAnt project property strData can be accessed from the C# script. The C# script also adds a new property data.out.value to the NAnt project.

NAnt script:
<property name="strData" value="Hi there"/>
    
<target name="ioTest">
    <CSScript file="script.data.io.cs" />
    <echo message="Data returned by the task: ${data.out.value}" />
</target>

C# script (script.data.io.cs):
using System;

class Script
{
    static public void Main(string[] args)
    {
        Console.WriteLine("strData = " + NAntRuntime.Project.Properties["strData"]);
        NAntRuntime.Project.Properties["data.out.value"] = "test return data";
    }
}

Returning an error from the script
If you want to return an error from the C# script you just need to throw an exception and it will be propagated to the NAnt runtime as a task error:

using System;

class Script
{
    static public void Main(string[] args)
    {
        throw new Exception("The script file has raised an error.");
    }
}

Executing C# code from NAnt script


Executing a single C# method

You can execute C# code embedded as CDATA into NAnt script. With embedded code you have an option of specifying a single method or full scale script.

The following is an example of a single method embedded script:

<target name="methodTest">
    <CSScript method="true" >
    <![CDATA[
      public static void Task()
      {
           Console.WriteLine("Hello World (from method)");
      }
    ]]>
    </CSScript>
</target>

Note that name of the method is irrelevant as long as it is static void method with no arguments it will be found and executed by CSScript task.

Executing a full C# script with custom entry point
If you need to execute complete C# script with the class infrastructure you can choose what static method to execute by specifying the entryPoint attribute value:

<target name="codeTest">
    <CSScript entryPoint="Task" >
    <![CDATA[
      using System;
      public class Script
      {
          public static void Task()
          {
               SayHello("Hello World (from 'Task' method)");
          }              
          
          public static void SayHello(string greeting)
          {
               Console.WriteLine(greeting);
          }
      }
    ]]>
    </CSScript>
</target>

Executing a full C# script with standard entry point
Should you decide to use the usual CLR assembly entry point you do not need to specify any task attributes:

<target name="codeTest">
    <CSScript>
    <![CDATA[
      using System;

      public class Script
      {
          public static void Main()
          {
               SayHello("Hello World (from code)");
          }             

          public static void SayHello(string greeting)
          {
               Console.WriteLine(greeting);
          }
      }
    ]]>
    </CSScript>
</target>

Reading project properties from C# script
You can access NAnt project variables through NAntRuntime.Project.Properties as in one of the examples above but if you need only to read property value from the script you can specify it directly in the C# code in the traditional NAnt way:

<property name="strData" value="Hi there"/>

<target name="codeTest">
    <CSScript method="true" >
    <![CDATA[
      public static void Task()
      {
           Console.WriteLine("${strData}");
      }
    ]]>
    </CSScript>
</target>


Debugging C# scripts
You can trigger attaching the system CLR debugger to C# script being executed by placing an Assert statement directly into the embedded code:

<target name="debugTest">
    <CSScript method="true" >
    <![CDATA[
      public static void Task()
      {
          System.Diagnostics.Debug.Assert(false);
          Console.WriteLine(NAntRuntime.Project.Properties["strData"]);
      }
    ]]>
    </CSScript>
</target>


The all samples above are taken from <cs-script>\Samples\NAnt\default.build NAnt script file.