Click here to Skip to main content
Click here to Skip to main content

NScript - A script host for C#/VB.NET/JScript.NET

, 18 Nov 2002
Rate this:
Please Sign up or sign in to vote.
NScript is a tool like WScript except that it allows for scripts to be written in .NET languages like C# and VB.NET
Prize winner in Competition ".NET Oct 2002"

Introduction

NScript is a tool similar to WScript except that it allows scripts to be written in .NET languages such as C#, VB.NET and JScript.NET. NScript automatically compiles the code into an assembly in memory and executes the assembly. The NScript setup application associates NScript with ".ncs" (for C# scripts), ".nvb" (for VB.NET scripts) and ".njs" (for JScript .NET scripts) file extensions. This enables any code written in these files to be executed directly by double clicking on these files in windows explorer. I wrote this tool when I needed to write a script for automating builds. A simple batch file was not sufficient for the task and I preferred to write code in C# as opposed to VBScript or JScript. This tool came in handy as I could modify the scripts easily and execute them by double clicking on the files in windows explorer.

Using NScript

  1. Download and unzip the setup
  2. Run the setup file NScript.msi. You need to have windows installer as well as the .NET framework installed on the machine before running the .msi file
  3. The setup automatically associates the file extensions ".ncs", ".nvb" and ".njs" with NScript.
  4. Write some code in C# like
    using System.Windows.Forms;
    
    class Test
    {
        static void Main(string[] args)
        {
            MessageBox.Show("Hello World!", "NScript");
        }
    };
  5. Save the file and give it an extension of .ncs

    You can execute the code in the file in any of the following ways:-

    1. Double click on the file in windows explorer in that case the script is launched using NScriptW
    2. At the command prompt type NScript MessageBox.ncs
    3. At the command prompt type NScriptw MessageBox.ncs
    4. You can execute code written in VB.NET or JScript.NET too. You need to save VB.NET files with the extension ".nvb" and JScript.NET files with extension ".njs"
  6. To cancel the execution when running in console mode press Ctrl+C or Ctrl+Break. When running under windows mode (i.e. NScriptW) an animating icon is shown in system tray. Double clicking on the icon cancels the execution.

The requirements for the code to be executed by NScript are:-

  1. The code should have a class defined.
  2. The class should have the Main method which takes single argument of type array of strings.
  3. You can refer to any assemblies listed in a file named NScript.nrf if it exists in the same directory as the NScript.Exe. Here is a sample content of NScript.nrf file
    System.Web.dll
    System.Web.RegularExpressions.dll
    System.Web.Services.dll
    System.Windows.Forms.Dll
    System.XML.dll
    
    It just has list of assembly names on each line.

How it Works?

The NScript solution has three projects:-

  1. NScript - a C# console application
  2. NScriptW - a C# windows application
  3. NScriptLib - a C# class library

NScript and NScriptW are very much similar to each other; the former can be used to run scripts that can output to console. NScript shows error messages in console where as NSCriptW shows error messages using message boxes. It is NScriptW which is associated with file extensions. Since there is lot of code that is shared by the two executables the common code is compiled in NScriptLib and both the executables refer to this class library.

The code behind NScript is pretty simple :-

  1. NScript creates an asynchronous delegate that does the compilation and execution asynchronously.
    CompileAndExecuteRoutine asyncDelegate = new 
        CompileAndExecuteRoutine(this.CompileAndExecute);
    
    IAsyncResult result = asyncDelegate.BeginInvoke(fileName, 
        newargs, this, null, null);
    
    //For a windows app a message loop and for a 
    // console app a simple wait
    ExecutionLoop(result);
    
    asyncDelegate.EndInvoke(result);
    
  2. The compilation and execution routine creates a separate AppDomain where it does the main compilation and execution. This is done because the user may require to cancel the execution of he script, in that case the AppDomain can simply be unloaded.
    //Create an AppDomain to compile and execute the code
    //This enables us to cancel the execution if needed
    executionDomain = AppDomain.CreateDomain("ExecutionDomain");
    
    IScriptManager manager = (IScriptManager)
        executionDomain.CreateInstanceFromAndUnwrap(
            typeof(BaseApp).Assembly.Location, 
            typeof(ScriptManager).FullName); 
    
    manager.CompileAndExecuteFile(file, args, this);
    

    IScriptManager interface is implemented by the type ScriptManager. Since any object has to be marshaled in order for it to be referenced from a separate AppDomain, we need the interface IScriptManager (as opposed to directly using the ScriptManager object). The ScriptManager type extends the MarshalByRefObject as it is marshaled by reference.

    public class ScriptManager : MarshalByRefObject, IScriptManager
    
  3. The main compilation and execution is carried out by the ScriptManager object's CompileAndExecute method. It used CodeDOM to carry out the compilation. It first figures out the CodeDomProvider to use based on the extension of the input script file
    //Currently only csharp scripting is supported
    CodeDomProvider provider;
    
    string extension = Path.GetExtension(file);
    
    switch(extension)
    {
    case ".cs":
    case ".ncs":
        provider = new Microsoft.CSharp.CSharpCodeProvider();
        break;
    case ".vb":
    case ".nvb":
        provider = new Microsoft.VisualBasic.VBCodeProvider();
        break;
    case ".njs":
    case ".js":
        provider = (CodeDomProvider)Activator.CreateInstance(
            "Microsoft.JScript", 
            "Microsoft.JScript.JScriptCodeProvider").Unwrap();
        break;
    default:
        throw new UnsupportedLanguageExecption(extension);
    }
    
  4. Once we have a CodeDomProvider we can compile the file into a temporary assembly using the ICodeCompiler interface
    System.CodeDom.Compiler.ICodeCompiler compiler = 
        provider.CreateCompiler();
    
    System.CodeDom.Compiler.CompilerParameters compilerparams = 
        new System.CodeDom.Compiler.CompilerParameters();
    
    compilerparams.GenerateInMemory = true;
    compilerparams.GenerateExecutable = true;
    
    System.CodeDom.Compiler.CompilerResults results = 
        compiler.CompileAssemblyFromFile(compilerparams, file);
    
  5. And finally the entry point method of the just compiled assembly is invoked.
    results.CompiledAssembly.EntryPoint.Invoke(
        null, BindingFlags.Static, null, new object[]{args}, null);
    

Conclusion

This is a very simple tool and I must confess that this is in no way an original idea. Don Box wrote a similar tool long time back but I could not locate it. As a result I decided to write my own. In future I hope to enhance it by allowing to compile and execute XML files similar to ".wsh" files. As usual any suggestions are welcome.

History

  • November 18, 2002 - Initial posting

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Rama Krishna Vavilala
Architect
United States United States
No Biography provided

Comments and Discussions

 
GeneralJ# support and XML script... Pinmemberbleekay28-Mar-07 6:50 
GeneralRe: J# support and XML script... Pinmemberbleekay28-Mar-07 7:40 
GeneralRe: J# support and XML script... Pinmemberbleekay29-Mar-07 5:48 
GeneralRe: J# support and XML script... Pinmemberbleekay14-Jun-07 4:29 
QuestionIntellisense? Pinmemberhamacatak24-Sep-06 23:31 
AnswerRe: Intellisense? Pinmemberhillcstephen11-Oct-06 5:17 
Generaladded stacktrace Pinmemberyeeting31-Aug-06 0:35 
QuestionJIT on run-time exceptions ? PinmemberciroE26-Apr-06 7:06 
Generalrun js file in application Pinmemberhamid_m23-Apr-06 8:05 
QuestionJavascript entry point? Pinmemberreinux10-Oct-05 10:07 
AnswerNevermind Pinmemberreinux10-Oct-05 10:14 
Generalsame example in VB.NET for a newbie Pinmembernevansmu7-Sep-05 5:12 
GeneralRe: same example in VB.NET for a newbie PinmemberDaveRogers11-Nov-05 0:04 
GeneralException has been thrown by the target of an invocation Pinmemberjhildeman9-Jul-05 5:57 
GeneralReturning values from script! Pinmemberplattfisk14-Oct-04 5:40 
GeneralRe: Returning values from script! PinmemberUnruled Boy9-Jun-05 22:55 
GeneralCongrats + File Association Question Pinmemberflipdoubt28-Mar-04 12:01 
QuestionAnyway to step? Pinmemberbillb211226-Dec-03 10:22 
GeneralIActiveScript PineditorHeath Stewart13-Oct-03 4:30 
GeneralRe: IActiveScript PinmemberRama Krishna13-Oct-03 4:39 
GeneralCommand Line argument problem Pinmemberbtcrew3-Apr-03 14:18 
GeneralPassing Global instances to script Pinmemberjmconnell200026-Mar-03 12:24 
GeneralSee Alintex Script Host PinmemberBaddabing7-Mar-03 14:02 
GeneralHandling cl arguments PinmemberHerman verschooten7-Mar-03 2:50 
AnswerRe: Handling cl arguments PinmemberLes Matheson28-Oct-05 18:34 
Generalreal commandline support and drag & drop PinmemberDolemite10-Feb-03 12:30 
GeneralRe: real commandline support and drag & drop PinmemberRama Krishna11-Feb-03 10:54 
GeneralRe: real commandline support and drag & drop PinmemberDolemite24-Feb-03 0:29 
GeneralPOP3 mail PinsussD@vR@t13-Jan-03 19:08 
GeneralBUG (?) PinmemberSpark2K30-Dec-02 5:58 
GeneralRe: BUG (?) PinmemberRama Krishna30-Dec-02 6:14 
GeneralRe: BUG (?) PinmemberSpark2K30-Dec-02 21:32 
GeneralRe: BUG (?) PinmemberRama Krishna31-Dec-02 2:57 
GeneralRe: BUG (?) PinmemberRobert Jeppesen12-Feb-03 2:11 
GeneralRe: BUG (?) Pinmemberaaava24-Feb-06 15:35 
QuestionLike Paul DiLascia did some Months ago in MSDNMag? PinsitebuilderUwe Keim19-Nov-02 2:38 
AnswerRe: Like Paul DiLascia did some Months ago in MSDNMag? PinmemberRama Krishna19-Nov-02 3:24 
GeneralRe: Like Paul DiLascia did some Months ago in MSDNMag? PinsitebuilderUwe Keim19-Nov-02 3:35 
GeneralRe: Like Paul DiLascia did some Months ago in MSDNMag? PinmemberJignesh I. Patel23-Jan-03 11:04 
GeneralBuild Tools for .NET PinmemberHeath Stewart19-Nov-02 1:35 
GeneralRe: Build Tools for .NET PinmemberRama Krishna19-Nov-02 2:03 
GeneralCommand line arguments PinmemberMarc Clifton19-Nov-02 1:15 
GeneralRe: Command line arguments PinmemberRama Krishna19-Nov-02 1:59 
GeneralNice idea... PinmemberRichard_D19-Nov-02 0:09 
GeneralRe: Nice idea... PinmemberRama Krishna19-Nov-02 1:10 
GeneralWonderful... PinmemberDavid Stone18-Nov-02 19:30 
GeneralRe: Wonderful... PinmemberRama Krishna19-Nov-02 2:08 
GeneralNice Job Rama PineditorNick Parker18-Nov-02 18:01 
GeneralRe: Nice Job Rama PinmemberRama Krishna19-Nov-02 3:25 
GeneralRe: Nice Job Rama PineditorNick Parker19-Nov-02 3:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140709.1 | Last Updated 19 Nov 2002
Article Copyright 2002 by Rama Krishna Vavilala
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid