by Asim Jalis, MetaProse.com
Here are the steps for how to write bat and cmd files with C#.
Here is the problem this solves: Frequently I just want to write a short C# snippet. I don't want to write it as a source file, compile it, and run it. I'd rather just put the snippet in a bat file and run the bat file. I want to shorten the code-compile-execute loop to just code-execute.
The following steps show you how to create CSBat.exe which solves this problem. Note: The in-memory compiler code was taken from Don Box's CSRepl from his blog.
- Create
hello.cmd
using the code below - Create
csbat.cs
using the code below - Type:
csc.exe csbat.cs /r:System.dll
- Type:
hello.cmd
- The
hello.cmd
script should print"Hello..."
. Now edit the script and run it again. It should run with the changes.
Here are the contents of hello.cmd. This is a sample cmd file that is able to run embedded C#.
@echo off
csbat.exe Chk %~f0 %*
goto :EOF
#! -*- csharp script start -*-
using System;
public class Chk
{
public static void Main(string[] args)
{
Console.WriteLine("Hello world from CSBat.");
Console.WriteLine("Argument count was: " + args.Length);
foreach (string arg in args)
{
Console.WriteLine("arg = " + arg);
}
}
}
Here are the contents of csbat.cs. This is the file you have to compile to create csbat.exe which is required to run bat files with embedded C#:
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.CodeDom;
using System.CodeDom.Compiler;
namespace CSBat
{
class Program
{
static string Eval(string program, string className, string[] args)
{
ICodeCompiler compiler = CodeDomProvider.CreateProvider("C#").CreateCompiler();
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
CompilerResults results = compiler.CompileAssemblyFromSource(cp, program);
if (results.Errors.HasErrors)
{
throw new ApplicationException(results.Errors[0].ErrorText);
}
else
{
Assembly assembly = results.CompiledAssembly;
Type target = assembly.GetType(className);
MethodInfo method = target.GetMethod("Main");
object[] parameters = new object[]{ args };
object result = method.Invoke(null, parameters);
return result == null ? null : result.ToString();
}
}
static void Main(string[] args)
{
try
{
if (args.Length < 2) { throw new ArgumentException("Usage: csbat CLASS FILE ARGS"); }
string className = args[0];
string filePath = args[1];
List<string> argList = new List<string>(args);
argList.RemoveAt(0);
argList.RemoveAt(0);
args = argList.ToArray();
string fileContents = File.ReadAllText(filePath);
fileContents =
Regex.Replace(fileContents, "^.*?\n#![^\n]*csharp script[^\n]*\n", "", RegexOptions.Singleline);
string result = Eval(fileContents, className, args);
}
catch(Exception e)
{
Console.WriteLine("Error: " + e.Message);
}
return;
}
}
}