Introduction
I needed to create a script of medium complexity that goes along these lines:
- Take a list of databases.
- Each database has an SVN folder, list of files to execute (with possible wildcards), and list of files to skip.
- For each database, perform “
get
” on the SVN folder, ignore the excluded files and run files from the “execute
” list in the order specified, respecting the wildcards.
What do they use to write such scripts these days? My first attempt was in NAnt. We already use NAnt for continuous integration and it seems to work reasonably well with files and external programs. The problem I had with NAnt is that it lacks adequate control structures and data types. All properties are string
s, and I needed structured data. The only type of for
loop is iteration over a delimited string
(or files in a directory). There are no parameterized function calls, although they can be simulated (poorly) with setting global properties and calling a target.
Then I briefly thought about writing it in...
C#
...but rejected the idea, since I wanted the script to be easily modifiable, and the compilation step gets in the way of that. Also, in compiled languages like C# script parameters are traditionally passed either via command line or via config file that must be parsed. My parameters were too big for the command line, and writing a parser was not in my plans. It is possible to do dynamic compilation in C#, but it is quite cumbersome. You don’t want your config file to start with something like using System; class Config { ConfigItem[] Data = ...
, do you?
My next thought was...
Powershell
...but this one is shipped only with the newest version of Windows Server, and we are not there yet. On older versions, it requires installation with admin rights. It may be easier to get an audience with the Pope of Rome than to install an app with admin rights on a production box in a huge financial corporation.
I then settled on...
JavaScript (WSH)
...and it worked, but I was plagued by various issues. First off, WSH does not seem to have a built-in way to execute an external command that sends output to current console window and wait for the result. You get either asynchronous execution without wait in current window (Exec
), or optionally synchronous execution in external window (Run
). I ended up writing a piece of code that uses Exec
and then polls the process for the exit status.
Also, WSH version of JavaScript lacks support for include
files. My script became big enough that I wanted it, primarily to separate config from code. One can use an eval
call to read and execute external file, or use WSF files, but both of these options greatly mess up line numbers and make detecting errors virtually impossible.
var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
function include(fileName)
{
eval(fileSystem.OpenTextFile(fileName, 1).ReadAll());
}
There are, of course, other alternatives: maybe I will try Python next time. But the situation with a scripting solution available on all currently active versions of Windows is bleak. Powershell would be a reasonably good answer if not for Microsoft’s love of admin-rights installers. Requiring an admin right installer is a huge demotivator in the corporate world.
CodeProject