Implementing a command line interpreter - c#

In terminal or cmd, you can write commands, in which there is a main command and then sub-commands, or arguments and stuff...like this:
cd Desktop\Folder
lst
Format E: /fs:FAT32
I want to create a C# console application that could execute predefined commands like this, but which could also split up main commands and sub-commands, in which some could be optional and some not. I have tried just taking all as string and then splitting it to array and creating if(s) and switch and cases, but it looks really bad and hardly manageable. I'm sure that in the OS's terminal or cmd it's build in another way. Could you help me understand the basic structure of such an application?

Here, have a look at this concept.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SharpConsole
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Welcome to SharpConsole. Type in a command.");
while (true)
{
Console.Write("$ ");
string command = Console.ReadLine();
string command_main = command.Split(new char[] { ' ' }).First();
string[] arguments = command.Split(new char[] { ' ' }).Skip(1).ToArray();
if (lCommands.ContainsKey(command_main))
{
Action<string[]> function_to_execute = null;
lCommands.TryGetValue(command_main, out function_to_execute);
function_to_execute(arguments);
}
else
Console.WriteLine("Command '" + command_main + "' not found");
}
}
private static Dictionary<string, Action<string[]>> lCommands =
new Dictionary<string, Action<string[]>>()
{
{ "help", HelpFunc },
{ "cp" , CopyFunc }
};
private static void CopyFunc(string[] obj)
{
if (obj.Length != 2) return;
Console.WriteLine("Copying " + obj[0] + " to " + obj[1]);
}
public static void HelpFunc(string[] args)
{
Console.WriteLine("===== SOME MEANINGFULL HELP ==== ");
}
}
}
The basic idea is to generalize the idea of a command. We have a Dictionary, where the key is a string (the command's name), and the value you get from the dictionary is a function of type Action<string[]>. Any function which has the signature void Function(string[]) can be used as this type. Then, you can set up this dictionary with a bunch of commands and route them to the functions you want. Each of these functions will receive an array of optional arguments. So here, the command "help" will be routed to the HelpFunc(). And the "cp" command e.g. will receive an array of filenames. The parsing of the command is always the same. We read a line, split it a space. The first string is the program's name, command_main here. If you skip the first string, you'll get an enumeration of all the other subcommands or switches you typed in. Then, a lookup in the dictionary is being done to see if there is such a command. If yes, we get the function and execute it with the arguments. If not, you should display "command not found" or something. All in all, this exercise can be minimized to looking up a function in a dictionary of possible command strings, then executing it. So a possible output is
Welcome to SharpConsole. Type in a command.
$ help
===== SOME MEANINGFULL HELP ====
$ cp file1 otherfile2
Copying file1 to otherfile2
$ python --version
Command 'python' not found
$ ...

LXSH
It's a command interpreter similar to CMD or Bash.
We've distributed it under MIT license, a shell with some functionalities in C# (.NET Core). You can contribute if you wish on
GitHub.
To solve the problem of matching a given token (part of the command line) with a builtin or a command, we use a dictionary.
However, we don't index the programs in the path for the moment. We just combine the name of the program with all the paths in the %PATH% variable.
Capture input
Expand environment variables, expand aliases
Try to match a builtin and run it if there is a match
Try to match with a program in %PATH% / $PATH
Run the program or display error
While you are unlikely to find the internal working of CMD (because it's closed source), you can find easily unix shell (bash, sh, zsh, etc..) information.
Links:
Bash Reference
Zsh Reference
TCSH Reference

Related

System.CommandLine parsed values don't match input

I am trying to use System.CommandLine and I haven't been able to get my handler to see any of the values that I'm passing in. I've tried the simplest command line program just to see if any values make it through and so far I haven't been successful. I am targeting .NET 4.7.2 and I'm using System.CommandLine 2.0.0-beta1.20574.7
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
static class Program
{
public static void Main(string[] args)
{
var rootCommand = new RootCommand
{
new Option("--continue", "continue option")
};
rootCommand.Description = "Testing System.CommandLine";
rootCommand.Handler = CommandHandler.Create<bool>
((willContinue) => run(willContinue));
rootCommand.Invoke(args);
}
private static void run(bool willContinue)
{
Console.WriteLine(willContinue);
}
}
No matter how I call my application, I am not seeing the value of willContinue come across as true.
myapp.exe --continue -> False
myapp.exe --cont -> Unrecognized command or argument '--cont' (my options are at least getting recognized)
myapp.exe --continue true -> Unrecognized command or argument 'true'
myapp.exe --help ->
myapp:
Testing System.CommandLine
Usage:
myapp [options]
Options:
--continue continue option
--version Show version information
-?, -h, --help Show help and usage information
You need to fix 2 things:
add the option type, which is bool
change the name of the option to match the parameter name
the following command works:
var rootCommand = new RootCommand
{
new Option<bool>("--willContinue", "continue option")
};
and call it like so
myapp.exe --willContinue true
the option name and parameter name don't always have to match-up, but in this case it doesn't work because 'continue' is a reserved word
I wanted to add an answer to be very clear about exactly what resolved my problem
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
static class Program
{
public static void Main(string[] args)
{
var rootCommand = new RootCommand
{
new Option("--willContinue", "continue option")
// ^This option name
};
rootCommand.Description = "Testing System.CommandLine";
rootCommand.Handler = CommandHandler.Create<bool>
((WiLLCoNtInUe) => run(WiLLCoNtInUe));
// ^ HAS to match this parameter name where the command handler is created.
// but does not have to match case
rootCommand.Invoke(args);
}
private static void run(bool canBeSomethingElse)
// Because of how this is called ^ this does not have to match
{
Console.WriteLine(canBeSomethingElse);
}
}
Because the Argument/Option/Command/anything else that can be added to a Command object has to match the name of the parameter used when creating the CommandHandler, the names used can't have spaces, begin with numbers, or use a C# keyword (not having spaces is not a problem for most items because it would be silly/impossible to have an option --will continue, but with arguments you don't have to put the name of the argument into your command line call because it is listed in the usage as <argument name> and the argument is read in by position, so I was wanting to use an argument name like <file directory>, but that doesn't work because you can't have a variable name with spaces in it)

Creating a command line in C# that includes file path

I am trying to create a project that accepts a configuration file and 2 comparison files using a command line arguments with the paths to these files included. Would I construct this the same way you would pass any command line argument? Sorry I am new to this so I am not sure if there is an exception when trying to pass files.
Can I get an example of how this would be done? Here is a picture of the directions of what exactly I have been asked.
Accept the following command line arguments:
Configuration file (with path) (described below)
Comparison File 1 (with path)
Comparison File 2 (with path)
Take a look at the documentation of Main function arguments
Assuming this is your main function and you want to accept 3 parameters:
static int Main(string[] args)
{
// check the length of args for validation.
// args[0] -> Configuration file
// args[1] -> Comparison File 1
// args[2] -> Comparison File 2
..... DO SOMETHING...
return 0;
}
Usage (from command line or debugger):
SomeProgram.exe "ConfigFilePath" "ComparisonFile1" "ComparisonFile2".
Because I really like this nuget(No association just a fan). Here is an example of it using CommandLineUtils
First add an new project with dotnet new consol TestConsolUtils then add the nuget dotnet add package McMaster.Extensions.CommandLineUtils then copy this code to the program class.
using McMaster.Extensions.CommandLineUtils;
using System;
namespace ConsolUtilsTest
{
class Program
{
public static int Main(string[] args)
=> CommandLineApplication.Execute<Program>(args);
[Argument(0, Description = "Configuration file")]
[FileExists]
public string ConfigurationFile { get; }
[Argument(1, Description = "Comparison file 1")]
[FileExists]
public string ComparisonFile1 { get; }
[Argument(2, Description = "Comparison File 2")]
[FileExists]
public string ComparisonFile2 { get; }
private void OnExecute()
{
Console.WriteLine(ConfigurationFile);
Console.WriteLine(ComparisonFile1);
Console.WriteLine(ComparisonFile2);
}
}
}
do a dotnet build
Go to the dll folder that was just build most likely in Debug\netcoreapp2.2\
Create a fake file A.json this is required because the utility will check if the file exists.
Run it with dotnet command
dotnet TestConsolUtils.dll A.json A.json A.json
There are a lot more you can do with this utill just look at the documentation.

FileSystem.Print has invalid arguments

I am using this below code to print my bill. I am getting the following error "Filesystem.Print has invalid arguments",Please Help in overcoming this error.
using Microsoft.Visualbasic;
.......................
public void PrintHeader()
{
FileSystem.Print(eInit + eCentre + "My Shop","");
FileSystem.Print("Tel:0123 456 7890","");
FileSystem.Print("Web: www.ame.com");
FileSystem.Print("sales#ame.com");
FileSystem.Print("VAT Reg No:123 4567 89" + eLeft);
PrintDashes();
}
public static void Print(
int FileNumber,
params Object[] Output
)
This is obviously a Visual Basic function. FileNumber is the handle of a file opened with FileOpen (which is a remnant of OPEN from Visual Basic 6.0 and older).
Example:
int myFileHandle = 1;
FileSystem.FileOpen(myFileHandle, "log.txt", OpenMode.Output);
FileSystem.Print(myFileHandle, "Hello", " ", "World!");
FileSystem.FileClose(myFileHandle);
You need to open a file with a specified handle first, and pass it into FileNumber.
Another better solution is to not use these API's as they are extremely outdated. Prefer the System.IO namespace.
edit:
To use the System.IO namespace instead you would open a StreamWriter:
var writer = new StreamWriter("mybill.txt");
And your PrintHeader method would take a TextWriter input (StreamWriter extends TextWriter)
public void PrintHeader(TextWriter output)
{
output.WriteLine(eInit + eCentre + "My Shop");
output.WriteLine("Tel:0123 456 7890","");
output.WriteLine("Web: www.ame.com");
output.WriteLine("sales#ame.com");
output.WriteLine("VAT Reg No:123 4567 89" + eLeft);
output.WriteLine(new string('-', 20));
}
If you're feeling adventurous you can make it async as well
public async Task PrintHeaderAsync(TextWriter output)
{
await output.WriteLineAsync(eInit + eCentre + "My Shop");
await output.WriteLineAsync("Tel:0123 456 7890","");
await output.WriteLineAsync("Web: www.ame.com");
await output.WriteLineAsync("sales#ame.com");
await output.WriteLineAsync("VAT Reg No:123 4567 89" + eLeft);
await output.WriteLineAsync(new string('-', 20));
}
FileSystem.Print method looks like this:
public static void Print(
int FileNumber,
params Object[] Output
)
So you have to pass two arguments in the Print method, but in some cases you are passing only one argument, and thus you are getting that error.
The question seems to be "how do I print this?"
The solution would be that you would use System.Drawing.Printing namespace.
I however took it as a little challenge, so I made a PrinterWriter class which you use as a normal textwriter.
The source code can be found in this gist and its usage is simple:
using(var myPrinter = new PrinterWriter())
{
myPrinter.WriteLine("Hello World!");
}
You can give parameters to the constructor if you want to write to another printer or change the font (which defaults to Consolas 10pt).
The using is important because it starts printing when Dispose() is called.
Note: it doesn't do word wrap.

Print the source filename and linenumber in C#

Is there any way to retrieve the current source filename and linenumber in C# code and print that value in the console output? Like LINE and FILE in C?
Please advise.
Many thanks
Anders Hejlsberg presented new API for that in BUILD keynote:
Print current file name, method name and line number
private static void Log(string text,
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0)
{
Console.WriteLine("{0}_{1}({2}): {3}", Path.GetFileName(file), member, line, text);
}
Test:
Log(".NET rocks!");
Output:
Program.cs_Main(11): .NET rocks!
What's going on here?
You define a method with optional parameters and decorate them with special attributes. If you call method without passing actual arguments (leave defaults) - the Framework populates them for you.
This answer is outdated! See #taras' answer for more recent information.
No constant :(
What you can do is a lot uglier :
string currentFile = new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName();
int currentLine = new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileLineNumber();
Works only when PDB files are available.
You can use the StackTrace object from the System.Diagnostics namespace but the information will only be available if the PDB files are there.
PDB files are generated by default for both the Debug and Release builds the only difference is that Debug is setup to generate a full debug info where as the Release build is setup to only generate a pdb (full/pdb-only).
Console.WriteLine(new StackTrace(true).GetFrame(0).GetFileName());
Console.WriteLine(new StackTrace(true).GetFrame(0).GetFileLineNumber());
There are no constants defined for that as of now.
The .NET way of doing it is using StackTrace class.
It however works only for Debug builds. So in case you use it, you can have the code using StackTrace between
#if DEBUG
//your StackTrace code here
#endif
You can read about using #if preprocessors for your DEBUG vs. RELEASE builds in the following Stackoverflow thread.
C# if/then directives for debug vs release
EDIT: Just in case you still need this debugging information in release builds, read the following answer on Stackoverflow:
Display lines number in Stack Trace for .NET assembly in Release mode
If you want some more internal detail, but you don't specifically need filename and line number, you can do something like this:
System.Diagnostics.Debug.Print(this.GetType().ToString() + " My Message");
This has an advantage over printing out the filename in that if you put this in a parent class, it will print out the child class name that is actually running the code.
If you wanted to write your own version of Debug.Assert, then here's a more complete answer:
// CC0, Public Domain
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System;
public static class Logger {
[Conditional("DEBUG")]
public static void Assert(bool condition, string msg,
[CallerFilePath] string file = "",
[CallerMemberName] string member = "",
[CallerLineNumber] int line = 0
)
{
// Debug.Assert opens a msg box and Trace only appears in
// a debugger, so implement our own.
if (!condition)
{
// Roughly follow style of C# error messages:
// > ideone.cs(14,11): error CS1585: Member modifier 'static' must precede the member type and name
Console.WriteLine($"{file}({line}): assert: in {member}: {msg}");
// Or more precisely match style with a fake error so error-parsing tools will detect it:
// Console.WriteLine($"{file}({line}): warning CS0: {msg}");
}
}
}
class Program {
static void Main(string[] args) {
Logger.Assert(1+1 == 4, "Why not!");
}
}
Try it online.

Is it possible to serialize a C# code block?

I'm using C# with .NET 3.5. Is it possible to serialize a block of code, transmit it somewhere, deserialize it, and then execute it?
An example usage of this would be:
Action<object> pauxPublish = delegate(object o)
{
if (!(o is string))
{
return;
}
Console.WriteLine(o.ToString());
};
Transmitter.Send(pauxPublish);
With some remote program doing:
var action = Transmitter.Recieve();
action("hello world");
My end goal is to be able to execute arbitrary code in a different process (which has no prior knowledge of the code).
YES!!!
We have done this for a very real case of performance. Doing this at runtime or using a DSL was not an option due to performance.
We compile the code into an assembly, and rip the IL out of the method. We then get all the metadata associated with this method and serialize the whole mess via XML, compress it, and put it in our database.
At re-hydration time, we re-constitute the IL with the metadata using the DynamicMethod class, and execute it.
We do this because of speed. We have thousands of little blocks of code. Unfortunately, to compile a block of code and run it on the fly takes at least 250 ms, which is way too slow for us. We took this approach, and it is working REALLY well. At run-time, it takes an unmeasurable amount of time to reconstitute the method and run it.
Only thing to keep an eye on... Signed assemblies and Unsigned assemblies cannot mix the serialized method data.
You could try to use IronPython in your project. It's trivial to do what you are asking in Python. The Python code could call your C# methods. As for security, you could execute the code in a restricted environment of some kind (one example is RestrictedPython).
Generally speaking that sounds like a really bad idea and a big security hole.
You don't want another process to execute any code. Understand what you really need another process to do and build a little DSL around it.
You could also send it as a string then use the CodeDomProvider to compile it, same result. I have an example bit of code thus:
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.CSharp;
namespace DynamicCodeApplication
{
class azCodeCompiler
{
private List<string> assemblies;
public azCodeCompiler()
{
assemblies = new List<string>();
scanAndCacheAssemblies();
}
public Assembly BuildAssembly(string code)
{
CodeDomProvider prov = CodeDomProvider.CreateProvider("CSharp");
string[] references = new string[] { }; // Intentionally empty, using csc.rsp
CompilerParameters cp = new CompilerParameters(references)
{
GenerateExecutable = false,
GenerateInMemory = true
};
string path = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
cp.CompilerOptions = "#" + path + #"\csc.rsp";
CompilerResults cr = prov.CompileAssemblyFromSource(cp, code);
foreach (CompilerError err in cr.Errors)
{
Console.WriteLine(err.ToString());
}
return cr.CompiledAssembly;
}
public object ExecuteCode(string code,
string namespacename, string classname,
string functionname, bool isstatic, params object[] args)
{
object returnval = null;
Assembly asm = BuildAssembly(code);
object instance = null;
Type type = null;
if (isstatic)
{
type = asm.GetType(namespacename + "." + classname);
}
else
{
instance = asm.CreateInstance(namespacename + "." + classname);
type = instance.GetType();
}
MethodInfo method = type.GetMethod(functionname);
returnval = method.Invoke(instance, args);
return returnval;
}
private void scanAndCacheAssemblies()
{
/*
foreach (string str in Directory.GetFiles(#"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727"))
{
if (str.Contains(".dll"))
{
foreach (string st in str.Split(new char[] { '\\' }))
{
if (st.Contains(".dll"))
{
assemblies.Add(st);
}
}
}
}
* */
assemblies.Add("Accessibility.dll");
assemblies.Add("AspNetMMCExt.dll");
assemblies.Add("cscompmgd.dll");
assemblies.Add("CustomMarshalers.dll");
assemblies.Add("IEExecRemote.dll");
assemblies.Add("IEHost.dll");
assemblies.Add("IIEHost.dll");
assemblies.Add("Microsoft.Build.Conversion.dll");
assemblies.Add("Microsoft.Build.Engine.dll");
assemblies.Add("Microsoft.Build.Framework.dll");
assemblies.Add("Microsoft.Build.Tasks.dll");
assemblies.Add("Microsoft.Build.Utilities.dll");
assemblies.Add("Microsoft.Build.VisualJSharp.dll");
assemblies.Add("Microsoft.CompactFramework.Build.Tasks.dll");
assemblies.Add("Microsoft.JScript.dll");
assemblies.Add("Microsoft.VisualBasic.Compatibility.Data.dll");
assemblies.Add("Microsoft.VisualBasic.Compatibility.dll");
assemblies.Add("Microsoft.VisualBasic.dll");
assemblies.Add("Microsoft.VisualBasic.Vsa.dll");
assemblies.Add("Microsoft.Vsa.dll");
assemblies.Add("Microsoft.Vsa.Vb.CodeDOMProcessor.dll");
assemblies.Add("Microsoft_VsaVb.dll");
assemblies.Add("mscorlib.dll");
assemblies.Add("sysglobl.dll");
assemblies.Add("System.configuration.dll");
assemblies.Add("System.Configuration.Install.dll");
assemblies.Add("System.Data.dll");
assemblies.Add("System.Data.OracleClient.dll");
assemblies.Add("System.Data.SqlXml.dll");
assemblies.Add("System.Deployment.dll");
assemblies.Add("System.Design.dll");
assemblies.Add("System.DirectoryServices.dll");
assemblies.Add("System.DirectoryServices.Protocols.dll");
assemblies.Add("System.dll");
assemblies.Add("System.Drawing.Design.dll");
assemblies.Add("System.Drawing.dll");
assemblies.Add("System.EnterpriseServices.dll");
assemblies.Add("System.Management.dll");
assemblies.Add("System.Messaging.dll");
assemblies.Add("System.Runtime.Remoting.dll");
assemblies.Add("System.Runtime.Serialization.Formatters.Soap.dll");
assemblies.Add("System.Security.dll");
assemblies.Add("System.ServiceProcess.dll");
assemblies.Add("System.Transactions.dll");
assemblies.Add("System.Web.dll");
assemblies.Add("System.Web.Mobile.dll");
assemblies.Add("System.Web.RegularExpressions.dll");
assemblies.Add("System.Web.Services.dll");
assemblies.Add("System.Windows.Forms.dll");
assemblies.Add("System.XML.dll");
assemblies.Add("vjscor.dll");
assemblies.Add("vjsjbc.dll");
assemblies.Add("vjslib.dll");
assemblies.Add("vjslibcw.dll");
assemblies.Add("vjssupuilib.dll");
assemblies.Add("vjsvwaux.dll");
assemblies.Add("vjswfc.dll");
assemblies.Add("VJSWfcBrowserStubLib.dll");
assemblies.Add("vjswfccw.dll");
assemblies.Add("vjswfchtml.dll");
assemblies.Add("Accessibility.dll");
assemblies.Add("AspNetMMCExt.dll");
assemblies.Add("cscompmgd.dll");
assemblies.Add("CustomMarshalers.dll");
assemblies.Add("IEExecRemote.dll");
assemblies.Add("IEHost.dll");
assemblies.Add("IIEHost.dll");
assemblies.Add("Microsoft.Build.Conversion.dll");
assemblies.Add("Microsoft.Build.Engine.dll");
assemblies.Add("Microsoft.Build.Framework.dll");
assemblies.Add("Microsoft.Build.Tasks.dll");
assemblies.Add("Microsoft.Build.Utilities.dll");
assemblies.Add("Microsoft.Build.VisualJSharp.dll");
assemblies.Add("Microsoft.CompactFramework.Build.Tasks.dll");
assemblies.Add("Microsoft.JScript.dll");
assemblies.Add("Microsoft.VisualBasic.Compatibility.Data.dll");
assemblies.Add("Microsoft.VisualBasic.Compatibility.dll");
assemblies.Add("Microsoft.VisualBasic.dll");
assemblies.Add("Microsoft.VisualBasic.Vsa.dll");
assemblies.Add("Microsoft.Vsa.dll");
assemblies.Add("Microsoft.Vsa.Vb.CodeDOMProcessor.dll");
assemblies.Add("Microsoft_VsaVb.dll");
assemblies.Add("mscorlib.dll");
assemblies.Add("sysglobl.dll");
assemblies.Add("System.configuration.dll");
assemblies.Add("System.Configuration.Install.dll");
assemblies.Add("System.Data.dll");
assemblies.Add("System.Data.OracleClient.dll");
assemblies.Add("System.Data.SqlXml.dll");
assemblies.Add("System.Deployment.dll");
assemblies.Add("System.Design.dll");
assemblies.Add("System.DirectoryServices.dll");
assemblies.Add("System.DirectoryServices.Protocols.dll");
assemblies.Add("System.dll");
assemblies.Add("System.Drawing.Design.dll");
assemblies.Add("System.Drawing.dll");
assemblies.Add("System.EnterpriseServices.dll");
assemblies.Add("System.Management.dll");
assemblies.Add("System.Messaging.dll");
assemblies.Add("System.Runtime.Remoting.dll");
assemblies.Add("System.Runtime.Serialization.Formatters.Soap.dll");
assemblies.Add("System.Security.dll");
assemblies.Add("System.ServiceProcess.dll");
assemblies.Add("System.Transactions.dll");
assemblies.Add("System.Web.dll");
assemblies.Add("System.Web.Mobile.dll");
assemblies.Add("System.Web.RegularExpressions.dll");
assemblies.Add("System.Web.Services.dll");
assemblies.Add("System.Windows.Forms.dll");
assemblies.Add("System.XML.dll");
assemblies.Add("vjscor.dll");
assemblies.Add("vjsjbc.dll");
assemblies.Add("vjslib.dll");
assemblies.Add("vjslibcw.dll");
assemblies.Add("vjssupuilib.dll");
assemblies.Add("vjsvwaux.dll");
assemblies.Add("vjswfc.dll");
assemblies.Add("VJSWfcBrowserStubLib.dll");
assemblies.Add("vjswfccw.dll");
assemblies.Add("vjswfchtml.dll");
return;
}
}
}
Compile it into a separate assembly, send the assembly, have the other process load it.
You might want to consider security implications.
Update: another idea would be to generate an expression tree and use this library to serialize it:
http://www.codeplex.com/metalinq/
It is an interesting challenge, but you should probably describe why you want to do this, since there is a lot of different approaches depending on your objective. As humpohl points out, there is also some pretty serious security issues.
"Serialized code" could just be source code or a compiled assembly, depending on your requirements. You probably don't need to use a seperate code serialization format.
If you want to generate code dynamically and pass that on, you could generate code using CodeDOM and compile it. However, you most likely dont need to generate completely arbitrary code.
Another option is using the DLR, and constraining the code to execute...

Categories