I'd call this an intermediate tutorial, you'll need a fairly decent understanding of basic C# structure, IO, and console input/output.

Let's take an example, let's say your making your own interpreted language in C#. You've got it all working and everything's going dandy.But then you realise since its interpreted and not compiled, everybody who makes an app in it, will have to distribute your interpror allong with another external file containing the code! Not very user friendly imho.

Here is a simple way to 'add-in' data to an already compiled EXE (eg. your interpretor) and then read it on loadup inside the EXE.

For this example well be making 2 apps, both console.
the first app will ask for your first and last name, then add this data to the end of the 2nd app.
The 2nd app will, when run, say hello, greeting you by your first and last name.
This may not seem very advanced, but the names could be replaced by, for example with the interretor idea, with code, or maybe debug settings.
And, you must remember that you changed what the runner says without changing a sinlge character in the source code.

Anywho lets get started, we'll start with the compiler, create a console app.

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Compiler
{
    class Program
    {
        static void Main(string[] args)
        {
            //I'll assume you understand all this ;)
            Program prog = new Program();
            prog.Start();
        }

        public void Start()
        {
            //I'll assume you understand all this ;)
            string fname = "";
            string lname = "";
            Console.Write("What your first name?");
            fname = Console.ReadLine();
            Console.Write("What your last name?");
            lname = Console.ReadLine();
            Console.WriteLine("Compiling...");
            DoCompile(fname, lname);
        }

        //This is the code that actually does the compiling.
        public void DoCompile(string fname, string lname)
        {
            //Copy the runenr exe to where we would like the compiled exe to be
            //we could just write to the runenr without copying, but that would
            //cause complicationg if we wanted to compile a second time
            File.Copy("runner.exe", "compiledrunner.exe");
            //Open the compiled exe(to-be) for writing, append must be set for true
            //else we'll just overwrite the program completely!
            StreamWriter SW = new StreamWriter("compiledrunner.exe", true);
            //Write "--DATA--" to the end of the file, this allows use to easilly find
            //the beginning of the compiled data
            //We make sure to add a new line char at beginning of line just to be
            //doiuble sure that the --DATA-- marker is on it's own line
            SW.WriteLine("\n" + XOR("--DATA--"));
            //Write the users first name now :)
            SW.WriteLine(XOR(fname));
            //then last name, don't forget to encrypt! :D
            SW.WriteLine(XOR(lname));
            //Close the stream writer, don't forget this :D
            SW.Close();
            Console.WriteLine("Compile complete!");
        }

        //Basic XOR encryption, this could be replaced with any other encryption you desire.
        //you could even not use encryption all-together, but then your would be too open
        //for hacking.
        //It's up to you.
        public string XOR(string input)
        {
            char[] chars = input.ToCharArray();
            string ret = "";
            foreach (char ch in chars)
            {
                ret += Convert.ToString(Convert.ToInt32(ch) ^ 2);
            }
            return ret;
        }
    }
}
Now we'll write the runner program, make it a console as well:

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Runner
{
    class Program
    {
        static void Main(string[] args)
        {
            //I'll assume you understand all this ;)
            Program prog = new Program();
            prog.Start();
        }

        public void Start()
        {
            //we want to get the full path of the current exe, including the filename
            string ExePath = System.Reflection.Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", "");
            StreamReader SR = new StreamReader(ExePath);
            string line = "";
            //Look for --DATA-- start
            while ((line = SR.ReadLine()) != XOR("--DATA--"))
            {
                //End of file but no --DATA--!
                if (SR.EndOfStream)
                {
                    //Exit, but you could do whatever
                    SR.Close();
                    Console.WriteLine("No data found!");
                    Console.ReadLine();
                    Environment.Exit(0);
                }
            }
            //Data has been found, start reading
            //Read firstname
            string fname = SR.ReadLine();
            //Read last name
            string lname = SR.ReadLine();
            //Close the stream reader
            SR.Close();
            //Decrypt first + last name
            fname = XOR(fname);
            lname = XOR(lname);
            Console.Write("Hello {0} {1}!",fname,lname);
            Console.ReadLine();
        }
        //Basic XOR encryption, this could be replaced with any other encryption you desire.
        //you could even not use encryption all-together, but then your would be too open
        //for hacking.
        //It's up to you.
        public string XOR(string input)
        {
            char[] chars = input.ToCharArray();
            string ret = "";
            foreach (char ch in chars)
            {
                ret += Convert.ToString(Convert.ToInt32(ch) ^ 2);
            }
            return ret;
        }
    }
}
Not the best way to add/read data to/from a runner, but its easy, and gets the job done.

Not: XOR is not the recommended encryption method, as it is fairly easy to break, I only used XOR for demonstration purposes and because it's an easy algorithm to write.

Hope that helps somebody