Batch to C# - Info

My first ever coding language was BATCH. Yes, the coding language for MS-DOS. I used it to make some really interesting things!

I once found myself browsing through the archives of my old computer and found some of my old BATCH files. The finding inspired me to make this program, a BATCH to C# converter.

I remember thinking to myself, you can pretty much do everything in BATCH with C#. Let’s find out if I was right!

The program is written in a way such that the code can be translated into any other coding language, as long as there is a specific compiler for it. (modular format)

There is a central “coding language”, which basically contains all of the data you will need to do the conversion. Visibility of classes, code’s function(to print text/pause/get user input/etc), methodnames, etc.

This batch to C# converter, however, is direct because I made the scripts for it before thinking of making the program modular.


Screenshots

Here’s what the UI looks like: UI The comboboxes at the top are currently empty because the program isn’t FULLY modular. Wouldn’t be that hard to complete the modular system, though.

Let’s run the code. Try and spot the difference between the C# output and BATCH outputt: BATCH C#

The first one is BATCH, the second one is C#.

You may have noticed, you can compile the C# script right from within the program. This is using the csc.exe file. You will be asked to navigate to it. It is usually in

(drive [normally "c"]):\windows\Microsoft.NET\Framework\v(version)\csc.exe

This is, providing you have .net framework installed.


Batch's "method" execution system.

Batch’s methods are executed in a much more different way to C#’s. For example:

@echo off
echo foooo:
:foo
    echo Hello
    goto loo
:joo
    echo joo
:loo
    echo World
:noo
    echo !!!!!
    pause

Will have the output:

foooo:
Hello
World
!!!!!
Press any key to continue . . .

Notice how the “loo” method goes directly to “noo” once it has finished executing. Notice how the “goto” to “loo” doesn’t return, rather it continues on to “noo”.

Let’s imagine that the “:” defines a method. A port of the above code, in C# will look like:

using System;

public class Program
{
    public static void Main()
    {Console.WriteLine(@"foooo:");}
    public static void foo()
    {
        Console.WriteLine("Hello");
    }
    public static void joo()
    {
        Console.WriteLine(@"joo");
    }
    public static void loo()
    {
        Console.WriteLine(@"World");
    }
    public static void noo()
    {
        Console.WriteLine(@"!!!!!");
        Console.WriteLine("Press any key to continue..."); Console.ReadKey();
    }
}

The execution order here is definitely not the same. Here’s the output:

foooo:

Simulating this Execution Order in C#

This is quite easy, all you have to do is make a list of all of the methods that you have in the batch script, in the order that they appear.

Then, when converting to C#, add a little line of code at the end which calls the next method. If there isnt a “next method”, then you know it must be the exit point of the application.

Here’s what the compiler gives as output now:

using System;

public class Program
{
    public static void Main()
    {
        Console.Clear(); //required line of code
        //echo is off from this point onwards!
        Console.WriteLine(@"foooo:");
            foo(); //proceed to next method
    }
    public static void foo()
    {
        Console.WriteLine(@"Hello");
        loo();
    }
    public static void joo()
    {
        Console.WriteLine(@"joo");
            loo(); //proceed to next method
    }
    public static void loo()
    {
        Console.WriteLine(@"World");
            noo(); //proceed to next method
    }
    public static void noo()
    {
        Console.WriteLine(@"!!!!!");
        Console.WriteLine("Press any key to continue..."); Console.ReadKey();
        Environment.Exit(0); //end of program
    }
}

Individual Line Handling

Console Output

This is probably harder than what you might have expected at first. @echo foo -> Console.WriteLine("foo"); Simple as that!… right?

nope, we need to consider all of the scenarios. Here’s what would currently happen in some scenarios:

BatchC#Output BatchOutput C#
`@echo "hello"``Console.WriteLine(""hello"");`"hello"Does Not Compile
`@echo %moo%``Console.WriteLine("%moo%");`vardata%moo%

The first issue is quite easy to solve, you just have to turn the string into a literal string or you can add the correct escape sequence.

The second issue will need some parsing. Let’s look at it again: @echo %moo%

  1. Get the position of the first "%", done using string.instanceOf();
  2. Get the position of the second "%", done by converting string into char array and cycling through
  3. Get the variable name by using substring.

And now that you have the variable name, in the C# version you must remember to:

  1. Add an ending quotation mark
  2. Add a plus symbol
  3. Add the variable name
  4. Add another plus symbol
  5. Add the literal string identifier "@"
  6. Add a starting quotation mark

That’s one way of doing it. Another way of doing it, and perhaps a more efficient way of doing it is that you just replace the two “%” symbols with a quotation mark and a plus or a plus then a quotation mark respectively.

So now the C# version is: Console.WriteLine(@""+moo+@"");

Great, it’s done! Nope… we still have not done every scenario.

What would happen in this scenario:

@echo var -> Console.WriteLine(@""+var+@"");

Most of you can probably immediately see that this is wrong. “var” can’t be set as a variable name in C# because the compiler will think your using it as a type.

Solution? All variables that are defined or called must have a “@” symbol in front of them.

Now the C# version is: Console.WriteLine(@""+@moo+@""); Great! I’m satisfied!

Colour

AKA “color”… This command in cmd paints the background a specific colour. The first letter/number corresponds to the foreground, the second corresponds to the background. Implementing that is not that hard at all. All you really need is a dictionary with keys of the letters and values of consolecolor values.

Then you could just simply do

Console.ForegroundColour =dictionary[string[0]];
Console.BackgroundColour = dictionary[string[1]];

Notice anything missing? When the color command is called in cmd, the console’s entire background/foreground gets repainted as that colour. Let’s implement that then!

Here’s what the program outputs when @color AE is inputted:

using System;

public class Program
{
    public static void Main()
    {
        Console.BackgroundColor = ConsoleColor.Green;

            int KXLXFHICTGUWIDTQQGWJJ = 0;int RVBABPYMZLKWVTNYAFGQPFE = Console.CursorLeft;int ODYYECCLDAQMQOVPMXFJKY = Console.CursorTop;while (KXLXFHICTGUWIDTQQGWJJ != Console.WindowHeight)
            {int KROYBEJQZZQLDWEBMNRA = 0;while (KROYBEJQZZQLDWEBMNRA != Console.WindowWidth){Console.Write(" ");KROYBEJQZZQLDWEBMNRA++;}KXLXFHICTGUWIDTQQGWJJ++;}Console.SetCursorPosition(RVBABPYMZLKWVTNYAFGQPFE, ODYYECCLDAQMQOVPMXFJKY);
Console.ForegroundColor = ConsoleColor.Yellow;
        Environment.Exit(0); //end of program
    }
}

It’s just a basic implementation of repainting the console background by filling it in with empty space. The variable names that are required to do this are randomly generated.

There is one problem with this, however, any text that was on the screen before is going to be shifted up and off the console window. There is a way to fix this, by repainting all the text on too, by storing all the text in a string builder and then setting console’s cursor position to the top left corner of the console, then re-printing the words and then setting the cursor position back to normal. This project, at the time of writing, has been deprecated long ago so I haven’t implemented that.

This will do for now!

pause

The program converts the pause command to:

Console.WriteLine("Press any key to continue..."); Console.ReadKey();

Pretty self-explanatory…

ECHO

In batch, when you run a command, the command is echoed in the console and then executed:

Console.WriteLine(System.Environment.CurrentDirectory+">SET /p var="); //echo is on so printing command

This has been simulated in this program. The program also recognises @echo off and @echo on commands. The program will not print the command if echo is off or if the line of code has a “@” before it (just like batch).

My aim is for the output to look exactly the same for both scripts. It wouldn’t really look the same if the echo features were not implemented.

The only thing that makes it look slightly different is the thing with the color command.

Variable Setting

This is pretty self-explanatory:

BatchC#
`SET /p var=``var @var = Console.ReadLine();`

There is no arithmetic support! :(

Title

This is rather straight forward.

@title banana` -> `Console.Title = @"banana";

Many batch features are supported. Many were probably not even mentioned here. At the end of the day, this is just proof of concept! Give the program a go if you want. The source is also available.

Time taken to write: 4-5h