Click here to Skip to main content
Click here to Skip to main content

Mini C# Compiler

, 25 Oct 2008
Rate this:
Please Sign up or sign in to vote.
MiniCompiler is a simple application for compiling single file C# source code. I've used interfaces provided by the .NET platform.
MiniCom.png

Code Explanation

C# MiniCompiler is a simple application that uses CSharpCodeProvider to create an instance of C# code compiler, then uses ICodeCompiler for all .NET compilers like VB, J#. So if we want to compile C# code, assign the interface ICodeProvider to provider.CreateCompiler().

Now we have the engine that compiles the code. We don't do anything unless we give this engine (ICodeProvider) some information about the code we want to compile. You pass this information to CompilerParameters. This information includes the Main class as you should tell it the name of the main class which it cannot get by itself. It also includes OutPutAssembly name, and referenced assemblies. So we have two problems.
The first is to give CompilerParameters Main class. We can give it from TextBox (from user), but we don't want that. We want to make it get the Main class automatically. So I wrote a basic parser (ManiPulateMainClass.cs) that manipulates the Main class from the source code.
The second problem is referenced assemblies. We can give the compiled assembly some referenced assemblies, but it may need it and may not need others. We can also make the user choose his assemblies. But many users don't know the path of all assemblies. So, what I did is parse the referenced namespaces from the code, such as "using System.Windows;". If the compiler sees this statement, it references System.Windows.dll and so on...

ManiPulateManiPulateMainClass.cs

This class has some functions that split the source code in namespaces, then classes, then check each class to see if this class is the main class or not by searching for the Main() function:

public static string GetMainClass(List<string> classname, List<string> classCode) 
{ 
    for (int i = 0; i < classCode.Count; i++) 
    { 
        if (classCode[i].Contains("Main(") && !classCode.Contains("\"")) 
        { 
            return classname[i]; 
        } 
    } 
    return "not found"; 
}

This function takes the class' sources codes as parameters and classNames that correspond to each class sourcecode. If it finds "Main()" without quotations, it means that it is the main class.

public void CompileCSharp(string code,string outputassembly ) 
{ 
    CSharpCodeProvider provider = new CSharpCodeProvider(); 
    ICodeCompiler compiler = provider.CreateCompiler(); 
#region CompilerParameters 
    CompilerParameters parameters = new CompilerParameters() 
    { 
        MainClass = Classname(code), 
            GenerateExecutable = true, 
            OutputAssembly = outputassembly, 
            IncludeDebugInformation = true, 
    }; 
    parameters.ReferencedAssemblies.Clear(); 
    foreach (Assembly asm in assemblies) 
    { 
        parameters.ReferencedAssemblies.Add(asm.Location); 
    } 
#endregion 
    CompilerResults result = compiler.CompileAssemblyFromSource(parameters, code); 
    if (result.Errors.Count == 0) 
    { 
        if (!System.IO.File.Exists(outputassembly)) 
        { 
            OnFileNotExists(new EventArgs()); 
            return; 
        } 
        ProcessStartInfo startInfo = new ProcessStartInfo(); 
        startInfo.FileName =outputassembly; 
        startInfo.WindowStyle = ProcessWindowStyle.Maximized; 
        startInfo.Arguments = "\\S"; 
        Process process = new Process(); 
        process.StartInfo = startInfo; 
        process.Start(); 
        IntPtr hwnd = GetConsoleWindow(); 
        ShowWindow(hwnd, 0); 
    } 
    else 
    { 
        foreach (CompilerError er in result.Errors) 
        { 
            List<string> cerrors = new List<string>(); 
            cerrors.Clear(); 
            cerrors.Add(
                 er.ErrorText+ " Line ("+er.Line.ToString()+") error :"+er.ErrorNumber ); 
            OnCompilationError(new ErrorEventArgs(cerrors)); 
        } 
        result.Errors.Clear(); 
    } 
}

First, we use ICodeProvider interface to compile CSharpCode:

ICodeCompiler compiler = provider.CreateCompiler();

Then, we create Compiler Parameters Object and give it some compilation information like the Main class. The Classname method uses the parser to get the Main class, so we call it to get the Main class name in this form, e.g.: Mynamespace.MyClass, OutPutAssembly property is the path of the output compiled program.

CompilerParameters parameters = new CompilerParameters() 
{ 
    MainClass = Classname(code), 
        GenerateExecutable = true, 
        OutputAssembly = outputassembly, 
        IncludeDebugInformation = true, 
}; 
//here we populate the compiled program with referenced assemblies 
foreach (Assembly asm in assemblies) 
{ 
    parameters.ReferencedAssemblies.Add(asm.Location); 
}

I got the referenced assemblies by parsing the referenced namespaces, but it is not a robust method. First, I collect all the common assemblies by getting the assemblies directories from the registry:

//get all assemblies directories 
public List<string> AssemblyDirectories() 
{ 
    List<string> assemblies = new List<string>(); 
    Microsoft.Win32.RegistryKey key = Registry.LocalMachine; 
    key = key.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders"); 
    string[] SubKeynames = key.GetSubKeyNames(); 
    foreach (string subkeys in SubKeynames) 
    { 
        RegistryKey subkey = Registry.LocalMachine; 
        subkey = subkey.OpenSubKey(
            @"SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\" + subkeys); 
        string[] l = subkey.GetValueNames(); 
        foreach (string v in l) 
        { 
            if (subkey.GetValueKind(v) == RegistryValueKind.String) 
            { 
                string value = (string)subkey.GetValue(v); 
                assemblies.Add(value); 
            } 
        } 
    } 
    assemblies.Add( Environment. @":\Windows\Microsoft.NET\Framework\v2.0.50727"); 
    return assemblies; 
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

ms_soft89
Web Developer
Egypt Egypt
I am Student @ Misr University 4 Science & Technology , began programming at early age , when I was 14 ,I have worked with vb6 and java alot but now I am interesting in c# & .NET Technologies , My favourite Programming language is C++

Comments and Discussions

 
Questionnice work sir but got a question here PinmemberElegiac28-May-13 22:50 
Generalmy vote of 5 Pinmemberwaqas31611-Nov-10 19:08 
GeneralMy vote of 2 PinmemberSDX200028-Oct-09 21:30 
GeneralRe: My vote of 2 PinmemberDelphiCoder21-Jun-12 10:01 
QuestionHow to select the source file? Pinmemberandre1234530-Oct-08 1:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 26 Oct 2008
Article Copyright 2008 by ms_soft89
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid