4

Short version: I want my program to be able to (read-only-)access its own source code during runtime. Is there a way to automatically package the source code into the dll during compilation?

Long version:

The background is that when an exception occurs, I want to automatically create a file containing some details of what happened. This file should, among other things, include the source code of the function that caused the problem. I want to send this file to other people by email, and the receiver will most likely not have (or not want to install) Visual Studio, so anything using symbol servers and the likes is out of question. It needs to be a plain text file.

Ideally I would somewhere find the related source code files and just copy out the relevant lines. You can safely assume that as long as I have a folder containing the entire source code, I will be able to locate the file and lines I want.

The best idea I could come up with so far -- and I have not looked into it in much detail because it seems messy to no end -- is to modify the MSBuild files to create a .zip of the source during compilation, and require .dll and .zip to reside in the same folder.

Most of the similar-sounding questions on stackoverflow that I found seem to deal with decompiling .dll files, which is not what I want to do. I have the source code, and I want to ship it together with the .dll in a convenient way.

Update: The really long version

Seems some people are seriously questioning why I would want to do that, so here's the answer: The main purpose of my software is testing some other software. That other software has a GUI. For an easy example, let's say the other software were the standard Windows calculator, then my testcase might look something like this:

calculator.Open();
calculator.EnterValue(13);
calculator.PressButtonPlus();
calculator.EnterValue(38);
calculator.PressButtonEnter();
int value = calculator.GetDisplayedValue();
Assert.That(value == 51);
calculator.Close();

These tests are intentionally written in a very human-readable way.

What I want to do when a problem occurs is to give the developer of the calculator a detailed description of how to reproduce the problem, in a way that he could reproduce by hand, without my software. (In this example, he would open the calculator, enter 13, press plus, and so on.)

Maybe another option would be to have each function calculator.Something() write out an information line to a log, but that would a) be a lot more work, b) only include the test run up to the point where it aborted, and c) bear some risk that writing the line is forgotten in one function, thereby giving an incorrect representation of what was done. But I'm open to other solutions than copying source code.

  • 3
    Something wrong with the debugging symbol files (.pdb)? – Oded Jan 09 '13 at 13:36
  • @Oded: his destination client has not and don't want to have VS or other tools. (for some reason) – Tigran Jan 09 '13 at 13:37
  • 1
    I'm not sure I understand the need to have the source of the function in the log output. Given exception information such as that printed by `Exception.ToString()` it's fairly easy to determine where the application crashed, and then browse to that function within visual studio to review it. Your client would not need visual studio for this, just a mechinism to get the logged info back to you – Crippledsmurf Jan 09 '13 at 13:40
  • @Tigran - So? Having the PDB files around means that the stack trace will include line numbers. What would the receiver do with the information if they can't compile the code if it even comes up with the report? – Oded Jan 09 '13 at 13:42
  • 1
    @Oded: Don't blame me, blame reciever :) I jsut repeat what is written in post. I *presume* there are some reasons for that – Tigran Jan 09 '13 at 13:43
  • @Tigran - I think OP has an idea of what the end result should _look_ like, but is dictating a _how_ instead of asking what is the right way to do it. – Oded Jan 09 '13 at 13:44
  • @Tigran Seems it was not clear enough *why the hell* I would want to do it this way, so I tried to update the question with even more background. (Sorry for the verbosity... ^_^;; ) – Birgit Vera Schmidt Jan 09 '13 at 14:21

3 Answers3

2

Take a look at this question: Do __LINE__ __FILE__ equivalents exist in C#?

C++ offers macros (__LINE__, __FILE__, and so on) that replace with the representing information during compile time. This means if you write something like this:

throw new CException(__FILE__);

it will compile to something like this:

throw new CException("test.cpp");

resulting in a hardcoded value. The C# compiler does not offer those macros and you are forced to use reflection to get the information about where the exception has been thrown. The way you can do it is described in the question linked above.

If you are not able to supply .pdb symbols then the default behaviour of Exception.ToString() (or StackTrace.ToString()) will not return you the line number, but the MSIL offsets of the operation that failed. As far as I can remember you can use the Stack Trace Explorer of ReSharper to navigate to the representing code (Not 100% sure about that, but there also was a question here on stackoverflow that mentioned this fact).

Community
  • 1
  • 1
Carsten
  • 11,287
  • 7
  • 39
  • 62
1

You can include copies of the source files as resources.

  • In the project folder, create a subfolder named Resources. Copy the source files there.
  • Create in the project a resource file, and then include the source copies you made into it.
  • Setup a pre-build event to copy the actual source files to Resources folder, so you always have updated copies. In the example I created, this worked well:

    copy $(ProjectDir)*.cs $(ProjectDir)Resources
    
  • In your code, now you can get the content of the files like this (I suppose the name of the resources file is Resource1.resx:

    // Get the source of the Program.cs file.
    string contents = Resource1.Program;
    

The project ended up like this:

Project tree

Doug
  • 6,322
  • 3
  • 29
  • 48
0

Yes, I also recommend packing up the sources in a .zip or whatever during MSBuild, and packaging that .zip with your application/dll. In runtime, when an exception occurs, you get the file and method name like Aschratt describes, extract the file from the .zip and find the method in it.

Jonathan
  • 6,939
  • 4
  • 44
  • 61