15

I want my application to be distributable as a single .exe file but I want to be able to get nice error reports with source code line numbers (the application simply sends email with exception.ToString() and some additional information when unhandled exception occurs).

Is there any way to embed .pdb into assembly?

Bobby
  • 11,419
  • 5
  • 44
  • 69
Konstantin Spirin
  • 20,609
  • 15
  • 72
  • 90

3 Answers3

8

Use MiniDumps instead of "exception.ToString()". It will give you a lot more information and does not need the .pdb to be distributed with the .exe.

Useful Link: Post-Mortem Debugging Your Application with Minidumps and Visual Studio .NET

Dietmar Hauser
  • 208
  • 1
  • 7
  • Absolutely, however you need to keep the PDBs of every build you ship for that to work reliably - best to setup a symbol server internally (see http://msdn.microsoft.com/en-us/library/ms680693(VS.85).aspx) – Christian.K Oct 06 '09 at 11:27
  • Can I make minidump of a running application? For example, if I get unhandled exception in WinForms, I will display error dialog to the user with an option to send error report and **continue** working with application (in contrast to terminating application). – Konstantin Spirin Oct 06 '09 at 18:29
5

I have used the following AssemblyResolve handler and then embedding both dll and pdb of any assemblies. You could set this up as anything that runs first thing in the application before dependencies are needed.

    private static void SetupEmbeddedAssemblyResolve()
    {
        // Based on http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx
        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        {
            var name = args.Name;
            var asmName = new AssemblyName(name);

            // Any retargetable assembly should be resolved directly using normal load e.g. System.Core issue: 
            // http://stackoverflow.com/questions/18793959/filenotfoundexception-when-trying-to-load-autofac-as-an-embedded-assembly
            if (name.EndsWith("Retargetable=Yes"))
            {
                return Assembly.Load(asmName);
            }

            var executingAssembly = Assembly.GetExecutingAssembly();
            var resourceNames = executingAssembly.GetManifestResourceNames();

            var resourceToFind = asmName.Name + ".dll";
            var resourceName = resourceNames.SingleOrDefault(n => n.Contains(resourceToFind));

            if (string.IsNullOrWhiteSpace(resourceName)) { return null; }

            var symbolsToFind = asmName.Name + ".pdb";
            var symbolsName = resourceNames.SingleOrDefault(n => n.Contains(symbolsToFind));

            var assemblyData = LoadResourceBytes(executingAssembly, resourceName);

            if (string.IsNullOrWhiteSpace(symbolsName))
            { 
                Trace.WriteLine(string.Format("Loading '{0}' as embedded resource '{1}'", resourceToFind, resourceName));

                return Assembly.Load(assemblyData);
            }
            else
            {
                var symbolsData = LoadResourceBytes(executingAssembly, symbolsName);

                Trace.WriteLine(string.Format("Loading '{0}' as embedded resource '{1}' with symbols '{2}'", resourceToFind, resourceName, symbolsName));

                return Assembly.Load(assemblyData, symbolsData);
            }
        };
    }

    private static byte[] LoadResourceBytes(Assembly executingAssembly, string resourceName)
    {
        using (var stream = executingAssembly.GetManifestResourceStream(resourceName))
        {
            var assemblyData = new Byte[stream.Length];

            stream.Read(assemblyData, 0, assemblyData.Length);

            return assemblyData;
        }
    }
nietras
  • 3,949
  • 1
  • 34
  • 38
  • 1
    I have made a short blog post with this as well at: http://www.codingmurmur.com/2014/02/embedded-assembly-loading-with-support.html – nietras Feb 18 '14 at 10:56
  • Woah. I knew you could do it with dll files, but this works with pdb files too? Neat. This does mean that, to use this to make a project into a single-file distribution, you'd need to put your main application into an external dll project, though. – Nyerguds Jan 02 '17 at 10:49
  • Well only if you don't want the main application pdb to be next to the exe. We can live with that. – nietras Jan 03 '17 at 11:25
  • I did say a _a single-file_ distribution ;) – Nyerguds Jan 04 '17 at 13:45
3

You could write a stub executable, that contains as embedded resources, both your actual executable and its pdb file. Upon starting the staub executable, it extracts the real executable and the pdb into a temporary directory and launches it.

Just like some Installers or other applications do.

I'm not sure if it is worth the extra effort though.

Christian.K
  • 47,778
  • 10
  • 99
  • 143
  • I also had this idea. This will also let me to apply compression to my binaries and make .exe smaller. The drawback is longer start up time. I just hope there's a simpler way of doing this. – Konstantin Spirin Oct 06 '09 at 18:25