Skip to content

Instantly share code, notes, and snippets.

@asimjalis
Created December 8, 2012 02:01
Show Gist options
  • Save asimjalis/4238173 to your computer and use it in GitHub Desktop.
Save asimjalis/4238173 to your computer and use it in GitHub Desktop.
How to use C# in bat and cmd files

How to use C# in bat and cmd files

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.

  1. Create hello.cmd using the code below
  2. Create csbat.cs using the code below
  3. Type: csc.exe csbat.cs /r:System.dll
  4. Type: hello.cmd
  5. 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;
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment