Introduction
I receive every month or so, a free magazine from VSJ. The articles in the magazine focus on "visual" languages such as Java, VB.NET, etc. Along with the articles, there is an "Outlook" section that discusses some recent developments or something similar, and also book reviews as well as the usual advertising.
In the Feb 5th edition, there was an article entitled "Script it with C#" (you can read the original here). This article is a .NET 2.0 version inspired by the original VSJ article but duly rewritten from the ground up.
Background
I contemplated changing the existing article to support the .NET 2.0 Framework back when it was still in Beta1, however when I tried this, it ran into a plethora of errors, and due to the time constraints, I dropped it. This evening, I decided that it would be nice if it did work under .NET 2.0 (just because of creating support for generics :) ) and so I did it.
Using the code
Included inside the zip file are the source files (or should I say file) along with a VC# Express project to compile it with. However, because it's just a single file, you should be able to compile it quite easily using csc.exe.
There are two routines inside the class, Main
and RunScript
.
Main
Main
, as usual, takes care of loading the program. In this case, all it does is check that a file was passed as the first argument, and then runs it passing the remaining arguments to the script. I decided to leave the first argument in the array so that the script has an easy way of determining where on the hard drive it is located. I.e. arg[0]=scripfile.csx
, arg[1...]=...
.
private static void Main(string[] args)
{
if ((args.Length == 0) || (!File.Exists(args[0])))
{
MessageBox.Show("A script file must be provided" +
" on the command-line.", "No Script File",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
CSScriptCompiler.RunScript(args[0], args);
}
}
RunScript
RunScript
takes care of all the hard work. Basically, the following steps occur:
- The script file is read in, if the line includes a
#using
, #import
, or #target
directive, then it is skipped, and these are explained below.
- The "Compiler" will insert
using
statements at the beginning of the source file and reference the necessary assemblies.
- The "Compiler" will then create a namespace, a class, and possibly a
Main
routine to encapsulate the script.
- It will then decide whether
Main
was declared with or without the command-line arguments option and invoke the appropriate method.
#using <namespace>
This is analogous to the C# using
statement, it simply imports a namespace so that you can use shorthand versions of the class names. I decided to prefix the statement with a #
because it is a bit simpler to avoid clashes with the actual C# statement.
A possibility that crossed my mind was to use regular expressions to increase the robustness of parsing, however, I decided to opt out because it was easier and quicker to accomplish.
#import <filename>
I never got on well with Dino's system of using a separate file to reference the DLLs, the task is made much easier if all the code is contained within one source file and that's why I introduced the #import
directive. This basically references an assembly so that you can use it in the script; the filename can be relative, absolute, or if it's on the paths searched by csc, then it can just be a filename.
#include "filename"
This is like the C #include
statement. All that really happens is this line is replaced with the contents of filename
. You can of course have includes within includes within includes (insert recursion loop here :) ).
Note: Remember to take this into account when debugging errors. I have not thought of an elegant solution which will keep track of the source files or line numbers.
Points of interest
Along with the source / demo project is an installer created with NSIS which will register the .csx extension for the compiler so that when you run a script file, it automatically executes css.exe, the C# script compiler. It also associates an icon with the extension to identify the file-type.
This installer will be compiled when you build the solution (if you have NSIS on your machine and installed in the default path).
Here is a list of the main features of the application:
- You can simply write code without having to bother about function declarations (see the helloworld.csx file in the samples directory).
- You can write code which incorporates functions; at the moment, you have to then write the main body of the script file in a valid
Main
routine.
- You can use any aspect of .NET you wish; for a simple Windows Forms example, look at the about_css.csx file in the samples directory.
If anybody comes up with any cool or useful scripts that could be included with the source, then send me an email through the CP website and if they're good enough I'll include them in the zip.
History
- 31st December, 2005
- 11th January, 2006
- Changed VS solution to compile as a console app so that the console is displayed for debugging.
- Added corrections to line numbers in the exception handling code.
- 20th January, 2006
- Improved code logic to remove the error message: "Error in source, probably forgot a ; blah blah blah (this was introduced because I couldn't be bothered to code around it previously, but I've done it now :) ).
- Removed the WinEXE / EXE target option because the console is displayed as the output window for the program so there was no point to it.
- 25th January, 2006
- Added
#include
statement.