CS-Script - custom module for C# scripting

Below are the first steps toward a module for allowing C# scripting from within Robin, as we’ve already got VBScript from within the System module.

This module uses CS-Script. It has a DLL called CSScriptLibrary.dll, used here. You can install it in your Custom Module from Visual Studio with the NuGet package manager. There are many dependencies, so it takes a while.

Your release folder will be jam-packed, but all you need to copy to your Custom Modules folder is CSScriptLibrary.dll, and your custom module. For testing, this module is Modules.CSScript2.dll.

CS-Script allows “classless”, or rather “auto-classed” code.

Here’s an example of something that runs (believe it or not) from the cscs.exe command line:

//css_autoclass freestyle
using System.Windows.Forms;
using System;

MessageBox.Show("Hello, Robin!");

No entry point, no ‘void main(string[] args’, no classes. CS-Script generates the required code behind the scenes.

MessageBox is shown:

Code listing (sorry, imgur cropped the image):

The DLL operates a little differently. Below is the code listing from the class ‘CSScript2.ListInput.cs’ in my solution (there are a few others, none ready for prime time yet):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Robin.Core;
using Robin.Core.Attributes;
using CSScriptLibrary;
using System.Windows.Forms;

namespace Modules.CSScript2
{
    [Action(Order = 1)]
    [Throws("ActionError")] // TODO: change error name (or delete if not needed)
    public class ListInput : ActionBase
    {
        #region Properties

        // NOTE: You can find sample description and friendly name entries in Resources

        public bool Result { get; private set; }

        [InputArgument]
        public List<string> InputArgs { get; set; }

        [InputArgument]
        public int InputIndex { get; set; }

        [OutputArgument]
        public string OutputArg { get; set; }

        #endregion

        #region Methods Overrides

        public override void Execute(ActionContext context)
        {
            try
            {
                //css_autoclass freestyle
                string greeting = InputArgs[InputIndex];
                var SayHello = CSScriptLibrary.CSScript.LoadMethod(
                                        @"using System.Windows.Forms;
                          public static void SayHello(string greeting)
                          {
                              MessageBoxSayHello(greeting);
                          }
                          static void MessageBoxSayHello(string greeting)
                          {
                              MessageBox.Show(greeting);
                          }")
                                         .GetStaticMethod("*.SayHello", "");
                SayHello(greeting);                //TODO: add action execution code here
                OutputArg = "Robin says: " + greeting;
            }
            catch (Exception e)
            {
                throw new ActionException("ActionError", e.Message, e.InnerException); // TODO: change error name (or delete if not needed)
            }

            // TODO: set values to Output Arguments and Result here
            // Result = ...
            // OutputArgument1 = ...
        }

        #endregion
    }
}

As you can see, we accept an input argument of type List, which is compatible with Robin lists. We also accept an integer index to access elements of the list. The freestyle method SayHello() shows a MessageBox with our indexed argument passed in. After some string concatenation, Robin gets back an output argument.

A lot more flexibility might be possible if users could install CS-Script on their machines, and simply run scripts via System, but that is definitely not going to be possible for many (if not most) business users.

Regards,
burque505

3 Likes

Still can’t edit some of my own posts, sorry! Typos are forever . . . :grinning:

Code listing from above for the Robin script that got mangled:

set inputArgs to ["First in", "First out"]

Console.Write Message: inputArgs[1]


CSScript2.ListInput \
                InputArgs: inputArgs \
                InputIndex: 0 \
                OutputArg=> OutputArg

Console.Write Message: OutputArg

Regards,
burque505