Run - Time Compiling
by Retro
 
 
				                 R u n - T i m e   C o m p i l i n g             
				                         b y   R e t r o                         
				                                                                 
				                   1 7 t h   A p r i l   2 0 0 6                 
				                                                                 
				               h t t p : / / r e t r o . h o s t . s k           
				                     w w w . r r l f . d e . v u                 
				                                                                 
				
		*************************************************************************************		
		
		1.  I N T R O
		
		I'm going to show you today, on how you can compile source code at runtime in csharp.
		After finishing Letum I started to look into metamorphic code, after searching through
		google I came across a little something called csharp-scripting and what I will be showing
		you is exactly the same thing but within itself.
		
		
		2.  S Y N T A X
		
		We only need two namespaces to complete this task -	
		
		Microsoft.CSharp - Contains classes that support compilation and code generation using the C# language. 
		
		System.CodeDom.Compiler - Contains types for managing the generation and compilation of source code in 
		supported programming languages.
		
			
		3.  P A R A M E T E R S
				
		To initialize the compiler we do the following
		
		// Get the provider for Microsoft.CSharp
			CodeDomProvider provider = new CSharpCodeProvider();
			
		// CompilerParameters object represents the settings and options for an ICodeCompiler interface
			CompilerParameters cp = new CompilerParameters();
		
		 cp.GenerateExecutable = true;
		  If you set this to true, then when it compiles it will generate a executable file 
		  otherwise it will give you a dynamic link library.
		
		 cp.OutputAssembly = "test.exe";
		  Sets the name for the output.
		
		 cp.ReferencedAssemblies.Add( "System.dll" );
		  This adds an assembly reference.  I've read that you need to add each one for every assembly
		  you plan to use in your code, but while testing I found this is not the case. I managed
		  to use other references in my code by just using the above assembly.
		 
		 cp.GenerateInMemory = False;
		  When set to false it will save the assembly has a physical file, ie an executable file, otherwise
		  it will save it into memory.
		  
		 cp.WarningLevel = 3;
		  The warning level at which the compiler aborts compilation.
		  (The default warning level in MSVS8 is 4)
		
		 cp.TreatWarningAsErrors = false;
		  Sets whether the compiler should treat warning messages as errors.
		
		 cp.CompilerOptions = "/optimize";
		  Sets options for the compiler, the given example gives optimize output.
		  
		 cp.MainClass = "Sample.Class1";
		  If needed you can specify the class that contains the main method of the executable.
		
		 cp.EmbeddedResources.Add("Default.resources");
		  Set the embedded resource file of the assembly. This is useful for culture-neutral resources, 
		  or default (fallback) resources.
		
		 cp.TempFile = new TempFileCollection(".", true);
		  Set a temporary files collection. The TempFileCollection stores the temporary files generated 
		  during a build in the current directory, but does not delete them after compilation.

		
		
		4.  C O M P I L E R  R E S U L T S
		
		Now we have provided the compiler with the options for compilation, we can now go ahead and
		compile our source code. This is easily accomplished but the following line of code.
		
		CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);
		
		This will compile the code from a file, where the sourceFile will point to its full path,
		but you dont just have to compile by using this method though. The other ways in which it
		can be done are:
		
		 provider.CompileAssemblyFromDom     
		  Compiles an assembly based on the System.CodeDom trees contained in the specified array 
		  of CodeCompileUnit objects. 
		  
		 provider.CompileAssemblyFromSource
		  Compiles an assembly from the specified array of strings containing source code,
		  eg. a text box.
		  
		After compilation has been done we can now check for errors
		
		  if(cr.Errors.Count > 0)
		  {
			// Display compilation errors.
			Console.WriteLine("Errors Found!")
			
			foreach(CompilerError ce in cr.Errors)
			{
				Console.WriteLine("  {0}", ce.ToString());
			}
		  }
		  else
		  {
			// Compilation OK
			Console.WriteLine("Compilation done with no errors")
		  }
		  
		Hopefully now you've understood on how to compile code at runtime, at which you can
		use however you see fit
		  
		*************************************************************************************
		                               retrouk[AT]gmail.com