Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Forget PowerPoint – make a slideshow in… a debugger :)

, 24 Nov 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
The article describes how to make a slideshow in a debugger. It may help you understand the PDB api in System.Reflection.Emit as well as impress listeners on any debugging-related presentations:)

Few days ago I had a presentation in the Warsaw .NET Group about PDB files. To make the slideshow more attractive (or rather originalSmile | :) ) I decided to replace the PowerPoint with something more connected with the subject, such as… the Visual Studio debugger. The only question was how to actually achieve this. The idea grew in my head after reading a brilliant Mike Stall’s post about debugging dynamically generated code. Mike shows in it how to emit sequence points for a text file of your choice and so bind this file with the generated MSIL. If done correctly, the debugger will load the text file, allowing you to step through its content and at the same time execute the emitted MSIL. So what if we could use the presentation table of contents as our source file and for each title (line of the table of contents) emit MSIL which will present a corresponding slide in the console window? This will actually make the debugger play the role of the PowerPointSmile | :)

Prepare the content

Let’s start from a table of contents for a hypothetical 3-slides presentation:

Welcome

1. Slide1
1.1 Slide1.1
2. Slide2

Thank you

Save this content as a toc.txt file – this will be our source file. Now let’s prepare slides. You may create a sub-directory slides or even create a separate directories for each group of slides – as you will shortly see there is no restriction here. In our case let’s stay with the one-directory-for-all approach. Let’s now assume that we want some contents to be presented for slides entitled: Welcome, 1.1 Slide1.1 ,2. Slide2 and Thank you (we omit 1. Slide1 by purpose). As mentioned previously the slides will be presented on the console so we may safely store their contents in text files named adequately: welcome.txt, slide1.1.txt and slide2.txt. Example content for a welcome.txt might be as follows:

                     SAMPLE PRESENTATION
                     ===================

                      Sebastian Solnica

              http://lowleveldesign.wordpress.com

Now we need to prepare a mapping file that will map the slide title with its corresponding content. Create a new text file and fill it with the following text:

Welcome
 slides\welcome.txt
1.1 Slide1.1
 slides\slide1.1.txt
2. Slide2
 slides\slide2.txt
Thank you
 thank-you.txt

Each indented line stores a path to the content of the slide with the title above it. The titles must be the same as in the toc.txt file and the file paths must be valid (however as you can see not all titles need to be mapped).

Create the presentation compiler

Having the presentation content ready we now need to create an exe file that will be run by the debugger. I suppose that the easiest approach is to use classes from the System.Reflection.Emit namespace. The pseudo code for the compiler (or rather emitter) will be as follows:

var asm = new DynamicAssembly()
MakeDebuggable(asm)

var mappingsContent = ReadFile(toc_slides.txt)
var mappings = StoreMappingsInDictionary(mappingsContent) // slide title -> slide file

for each slideTitle in GetContent(toc.txt) {
  if (mappings.Contains(slideTitle)) {
    EmitMsilCodeThatWillReadAndPrintTheSlide(mappings[slideTitle]);
    MarkSequencePoint(currentLineNum); // binds a line of the source code with the emitted MSIL
  }
}

SaveAssembly(asm)

I will now explain few methods that occur in the code above that might have confused you (the C# source code that implements the above logic can be downloaded from here). MakeDebuggable is responsible for adding a DebuggableAttribute to the assembly. This attribute informs the JIT compiler that it should produce assembly code that will be debuggable (more here). To make the debugging process possible we also need to create a PDB file that will store the debug information for our module. ModuleBuilder contains a special method called DefineDocument that will do this for us. Here’s a C# code that implements all the logic described:

Type daType = typeof(DebuggableAttribute);
ConstructorInfo daCtor = daType.GetConstructor(new Type[] { typeof(DebuggableAttribute.DebuggingModes) });
CustomAttributeBuilder daBuilder = new CustomAttributeBuilder(daCtor, new object[] { 
    DebuggableAttribute.DebuggingModes.DisableOptimizations | 
    DebuggableAttribute.DebuggingModes.Default });
assemblyBuilder.SetCustomAttribute(daBuilder);

ModuleBuilder module = assemblyBuilder.DefineDynamicModule(outputFileName, true); // <-- pass 'true' to track debug info.

// Tell Emit about the source file that we want to associate this with. 
ISymbolDocumentWriter doc = module.DefineDocument(tableOfContentsPath, Guid.Empty, Guid.Empty, Guid.Empty);

EmitMsilCodeThatWillReadAndPrintTheSlide emits MSIL that will open the slide file, read it at once and print the content to the console. Ildasm the code below and you will get itSmile | :) (or check emitReadAndPrintSlideMethod in Program.cs from the slide compiler source code):

using (StreamReader reader = new StreamReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
   Console.Clear();
   Console.Write(reader.ReadToEnd());
}

To make the assembly smaller you may consider putting this logic in a separate method and emit just calls to this method with adequate parameters (this is what I do in the sample code). For each slide printed we need to inform the debugger which line of the source code (or table of contents in our caseSmile | :) ) should be highlighted. For this purpose we use MarkSequencePoint method of the ILGenerator instance:

ilGenerator.MarkSequencePoint(doc, currentLineNum, 1, currentLineNum, 100);

To make the debugging even more feasible I emit System.Diagnostics.Debugger.Break() call after the first sequence point (so even when starting with F5 the debugger should stop on the first slide).

Compile and showSmile | :)

By now we should have the presentation compiler and the presentation content (table of contents, slide files and slide title <-> slide file mapping file) ready. So it’s time to compile it and debug itSmile | :) If you are using my compiler run the following in the command window:

SlideCompiler.exe -files toc_slides.txt -o toc.exe toc.txt

This should produce a toc.exe file (and toc.pdb) that you can now open in Visual Studio (File->Open->Project/Solution…). After pressing F5 you should see something like:

By pressing F11 or F10 you may advance the slides. To move back just select the line before the slide you want to show, press Ctrl+Shift+F10 and then F10. You may also place breakpoints on your slidesSmile | :)

The code (and the sample presentation as well as my symbol presentation from WG.NET) can be found on my blog samples site.

Have fun and surprise you listeners on your next presentation! :)


Filed under: CodeProject, Debugging, Visual Studio

License

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

Share

About the Author

Sebastian Solnica
Software Developer (Senior)
Poland Poland
Interested in tracing, debugging and performance tuning of the .NET applications (especially ASP.NET).
 
If you find this article interesting, maybe you would like to pay me a visit: http://lowleveldesign.wordpress.com? Smile | :)

Comments and Discussions

 
GeneralMy vote of 5 PinmemberMattias Högström8-Sep-12 11:50 
Generalmethod names Pinmemberdave.dolan23-May-12 3:44 
GeneralMy vote of 5 PinmemberLeonardo Paneque2-May-12 4:54 
Questionnice PinmemberKanasz Robert29-Nov-11 23:51 
GeneralMy vote of 5 PinmemberSebastian Br.28-Nov-11 0:20 
GeneralMy vote of 5 PinmemberAbinash Bishoyi25-Nov-11 3:33 
GeneralMy vote of 5 Pinmemberbosedk22-Nov-11 23:51 
GeneralMy vote of 5 PinmemberPaulo Zemek22-Nov-11 8:16 
Very original!
GeneralMy vote of 5 PinmemberReiss22-Nov-11 6:25 

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 | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 25 Nov 2011
Article Copyright 2011 by Sebastian Solnica
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid